/*
 * @Author       : Bing Chen chenbing@iocharger.com
 * @Date         : 2024-05-31 11:32:16
 * @LastEditors  : Bing Chen chenbing@iocharger.com
 * @LastEditTime : 2025-03-15 12:51:13
 * @FilePath     : \openchaoji-corelib\secc\gbt27930\OpenChaoJi_secc_gbt27930_a.c
 * @Description  : secc的GB/T 27930 A类系统实现
 *
 * Copyright (c) 2025 OpenChaoJi
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the icense for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include "../include/OpenChaoJi_secc.h"

#if (OPENCHAOJI_CONFIG_ENABLE_GBT27930_A == CONFIG_YES)

struct OpenChaoJi_secc_gbt27930_a_data
{
    /* -------------- IDLE 模块 特来电 -------------- */
    struct {
        int dummy;
    } idle;

    /* -------------- Trigger 模块 特来电 -------------- */

    /* -------------- 充电握手 模块 国网 -------------- */
    struct {
        int seftcheck_ok;           // 充电机自检结果, 0 未完成, 1 成功, 2 失败
        int seftcheck_start;        // 充电机自检启动标识
    } handshake;

    /* -------------- 参数配置 模块 国网 -------------- */
    struct {
        int bcp_timer_start;        // 首次发送CRM=AA时, 打开BCP报文超时定时器
    } config;

    /* --------------  充电 模块 银河龙芯 -------------- */
    struct {
        int bcl_timer_start;        // 首次发送SPN2830=0xAA的CRO报文时, 打开BCL报文超时定时器
        int bsm_rcvd_flag;          // BSM报文接收标识, 首次接收到BSM报文时置位
        int cst_send_flag;          // CST报文发送标识, 首次发送CST报文时置位

        struct OpenChaoJi_secc_gbt27930_charging_requirement_parameter requirement_parameter; // 车辆请求参数
        unsigned int volt_power_module; // 当前设置给模块的电压
        unsigned int curr_power_module; // 当前设置给模块的电流
    } charge;

    struct OpenChaoJi_secc_app_start_parameter app_start_parameter;

    /* --------------  END 模块 银河龙芯 -------------- */

    /* --------------  FAULT 模块 银河龙芯 -------------- */

    /* -------------- 通用数据 国网 -------------- */

    int protocol_version;           // 对端通信协议版本
    int reconnect_flag;             // 通信重连标识
    int reconnect_cnt;              // 通信重连次数
    int precharge_status;           // 预充状态
    int stop_status;                // 停机泄放状态
    int stop_ticks;                 // 停机超时时间

    struct OpenChaoJi_os_soft_timer tcp_chm;
    struct OpenChaoJi_os_soft_timer tcp_crm;
    struct OpenChaoJi_os_soft_timer tcp_cts;
    struct OpenChaoJi_os_soft_timer tcp_cml;
    struct OpenChaoJi_os_soft_timer tcp_cro;
    struct OpenChaoJi_os_soft_timer tcp_ccs;
    struct OpenChaoJi_os_soft_timer tcp_cst;
    struct OpenChaoJi_os_soft_timer tcp_csd;
    struct OpenChaoJi_os_soft_timer tcp_cem;

    struct OpenChaoJi_os_soft_timer tco_bhm;
    struct OpenChaoJi_os_soft_timer tco_brm;
    struct OpenChaoJi_os_soft_timer tco_bcp;
    struct OpenChaoJi_os_soft_timer tco_bro;
    struct OpenChaoJi_os_soft_timer tco_bro_aa;
    struct OpenChaoJi_os_soft_timer tco_bcl;
    struct OpenChaoJi_os_soft_timer tco_bcs;
    struct OpenChaoJi_os_soft_timer tco_bsm;
    struct OpenChaoJi_os_soft_timer tco_bst;
    struct OpenChaoJi_os_soft_timer tco_bsd;

    struct OpenChaoJi_os_soft_timer tco_cst;
    struct OpenChaoJi_os_soft_timer tco_csd;
    struct OpenChaoJi_os_soft_timer tco_cep;
    struct OpenChaoJi_os_soft_timer tco_bsup;
    struct OpenChaoJi_os_soft_timer tco_lock;
    struct OpenChaoJi_os_soft_timer tco_auxpower;
    struct OpenChaoJi_os_soft_timer tco_precharge;
    struct OpenChaoJi_os_soft_timer tco_stopping;

    struct OpenChaoJi_gbt27930_a_msg_chm msg_chm;
    struct OpenChaoJi_gbt27930_a_msg_crm msg_crm;
    struct OpenChaoJi_gbt27930_a_msg_cts msg_cts;
    struct OpenChaoJi_gbt27930_a_msg_cml msg_cml;
    struct OpenChaoJi_gbt27930_a_msg_cro msg_cro;
    struct OpenChaoJi_gbt27930_a_msg_ccs msg_ccs;
    struct OpenChaoJi_gbt27930_a_msg_cst msg_cst;
    struct OpenChaoJi_gbt27930_a_msg_csd msg_csd;
    struct OpenChaoJi_gbt27930_a_msg_cem msg_cem;

    struct OpenChaoJi_gbt27930_a_msg_bhm msg_bhm;
    struct OpenChaoJi_gbt27930_a_msg_brm msg_brm;
    struct OpenChaoJi_gbt27930_a_msg_bcp msg_bcp;
    struct OpenChaoJi_gbt27930_a_msg_bro msg_bro;
    struct OpenChaoJi_gbt27930_a_msg_bcl msg_bcl;
    struct OpenChaoJi_gbt27930_a_msg_bcs msg_bcs;
    struct OpenChaoJi_gbt27930_a_msg_bsm msg_bsm;
    struct OpenChaoJi_gbt27930_a_msg_bmv msg_bmv;
    struct OpenChaoJi_gbt27930_a_msg_bmt msg_bmt;
    struct OpenChaoJi_gbt27930_a_msg_bsp msg_bsp;
    struct OpenChaoJi_gbt27930_a_msg_bst msg_bst;
    struct OpenChaoJi_gbt27930_a_msg_bsd msg_bsd;
    struct OpenChaoJi_gbt27930_a_msg_bem msg_bem;

    int msg_bhm_ok;         // 接收到bhm报文
    int msg_brm_ok;         // 接收到brm报文
    int msg_bcp_ok;         // 接收到bcp报文
    int msg_bro_ok;         // 接收到bro报文
    int msg_bcl_ok;         // 接收到bcl报文
    int msg_bcs_ok;         // 接收到bcs报文
    int msg_bsm_ok;         // 接收到bsm报文

    int msg_bmv_ok;         // 接收到bmv报文
    int msg_bmt_ok;         // 接收到bmt报文
    int msg_bsp_ok;         // 接收到bsp报文
    int msg_bsd_ok;         // 接收到bsd报文
    int msg_bst_ok;         // 接收到bst报文
    int msg_bem_ok;         // 接收到bem报文

    /* -------------- 日志专用 -------------- */
    struct {
        struct OpenChaoJi_gbt27930_a_msg_chm msg_chm;
        struct OpenChaoJi_gbt27930_a_msg_crm msg_crm;
        struct OpenChaoJi_gbt27930_a_msg_cts msg_cts;
        struct OpenChaoJi_gbt27930_a_msg_cml msg_cml;
        struct OpenChaoJi_gbt27930_a_msg_cro msg_cro;
        struct OpenChaoJi_gbt27930_a_msg_ccs msg_ccs;
        struct OpenChaoJi_gbt27930_a_msg_cst msg_cst;
        struct OpenChaoJi_gbt27930_a_msg_csd msg_csd;
        struct OpenChaoJi_gbt27930_a_msg_cem msg_cem;

        struct OpenChaoJi_gbt27930_a_msg_bhm msg_bhm;
        struct OpenChaoJi_gbt27930_a_msg_brm msg_brm;
        struct OpenChaoJi_gbt27930_a_msg_bcp msg_bcp;
        struct OpenChaoJi_gbt27930_a_msg_bro msg_bro;
        struct OpenChaoJi_gbt27930_a_msg_bcl msg_bcl;
        struct OpenChaoJi_gbt27930_a_msg_bcs msg_bcs;
        struct OpenChaoJi_gbt27930_a_msg_bsm msg_bsm;
        struct OpenChaoJi_gbt27930_a_msg_bmv msg_bmv;
        struct OpenChaoJi_gbt27930_a_msg_bmt msg_bmt;
        struct OpenChaoJi_gbt27930_a_msg_bsp msg_bsp;
        struct OpenChaoJi_gbt27930_a_msg_bst msg_bst;
        struct OpenChaoJi_gbt27930_a_msg_bsd msg_bsd;
        struct OpenChaoJi_gbt27930_a_msg_bem msg_bem;
   } log_msg;
};

bool s_gbt_a_public_debug_enable = false;
void OpenChaoJi_debug_set_log_module_gbt_a_public(bool enable)
{
    s_gbt_a_public_debug_enable = enable;
}

/* -------------- Debug -------------- */

static int OpenChaoJi_gbt27930_a_secc_parse_data(struct OpenChaoJi_secc_context * context, struct OpenChaoJi_utility_data_buff_recv_data * recv_data);

static void OpenChaoJi_gbt27930_a_secc_running_data_timer_reset(struct OpenChaoJi_secc_context * context)
{
    LOG_NOTICE("[%d]STOP ALL TIMER", context->tag);

    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_chm);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_crm);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_cts);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_cml);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_cro);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_ccs);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_cst);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_csd);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_cem);

    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bhm);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_brm);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bcp);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bro);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bro_aa);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bcl);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bcs);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bsm);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bst);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bsd);

    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_cst);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_csd);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_cep);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bsup);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_lock);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_auxpower);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_precharge);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_stopping);

    return;
}

static void OpenChaoJi_gbt27930_a_secc_running_data_reset(struct OpenChaoJi_secc_context * context)
{
    LOG_STATUS_CHANGE("[%d]RESET RUNNING DATA", context->tag);

	memset(context->running_data.a, 0x00, sizeof(struct OpenChaoJi_secc_gbt27930_a_data));
    // CST
    context->running_data.a->msg_cst.error_code.bits.res = 0x03; // 保留位置1
    // CEM
    context->running_data.a->msg_cem.tout_code.all = 0xF0C0F0FC; // 保留位置1
    // CHM
    context->running_data.a->msg_chm.pro_version[0] = OPENCHAOJI_GBT27930_A_PROTOCOL_VERSION_TYPE_MAJOR(OPENCHAOJI_GBT27930_A_PROTOCOL_VERSION_TYPE_1_1_0); // 充电机通信协议版本号, 当前版本为 V1.1
    context->running_data.a->msg_chm.pro_version[1] = OPENCHAOJI_GBT27930_A_PROTOCOL_VERSION_TYPE_MINOR(OPENCHAOJI_GBT27930_A_PROTOCOL_VERSION_TYPE_1_1_0);
    context->running_data.a->msg_chm.pro_version[2] = OPENCHAOJI_GBT27930_A_PROTOCOL_VERSION_TYPE_TMP(OPENCHAOJI_GBT27930_A_PROTOCOL_VERSION_TYPE_1_1_0);
    // CRM
    context->running_data.a->msg_crm.recognition_result = OPENCHAOJI_GBT27930_A_RECOGNIZE_TYPE_NOT_RECOGNIZED; // 初始化辨识结果
    context->running_data.a->msg_crm.charger_id = OpenChaoJi_secc_app_get_charger_id(context); // 充电机编号
    OpenChaoJi_secc_app_get_charger_location(context, context->running_data.a->msg_crm.charger_location); // 充电机/充电站所在区域编码
    // CML 从app_start函数中传递参数（建议传最大值）, 需要APP启动后更新
    // context->running_data.a->msg_cml.max_output_voltage = context->running_data.a->app_start_parameter.parameter_max_charging_volt; // 充电机最高充电电压
    // context->running_data.a->msg_cml.min_output_voltage = context->running_data.a->app_start_parameter.parameter_min_charging_volt; // 充电机最低充电电压
    // context->running_data.a->msg_cml.max_output_current = 4000 - context->running_data.a->app_start_parameter.parameter_max_charging_curr; // 充电机最大充电电流
    // context->running_data.a->msg_cml.min_output_current = 4000 - context->running_data.a->app_start_parameter.parameter_min_charging_curr; // 充电机最小充电电流
    // CSD
    context->running_data.a->msg_csd.charger_id = OpenChaoJi_secc_app_get_charger_id(context); // 充电机编号

    OpenChaoJi_gbt27930_a_secc_running_data_timer_reset(context);

    return;
}

static void OpenChaoJi_gbt27930_a_secc_reset_to_default(struct OpenChaoJi_secc_context * context)
{
    LOG_STATUS_CHANGE("[%d] RESET TO DEFAULT", context->tag);

    OpenChaoJi_secc_utility_session_reset(context->context_session);
    OpenChaoJi_secc_utility_pilot_reset(context->context_pilot);

	OpenChaoJi_gbt27930_a_secc_running_data_reset(context);
}

static bool OpenChaoJi_gbt27930_a_secc_log_msg_set(struct OpenChaoJi_secc_context * context, struct OpenChaoJi_gbt27930_a_msg * msg)
{
    switch (msg->pid)
    {
    case OPENCHAOJI_GBT27930_A_PGN_CHM:
        if (memcmp(&context->running_data.a->log_msg.msg_chm, &msg->msg.chm, sizeof(msg->msg.chm)) != 0)
        {
            memcpy(&context->running_data.a->log_msg.msg_chm, &msg->msg.chm, sizeof(msg->msg.chm));
            return true;
        }
        return false;

    case OPENCHAOJI_GBT27930_A_PGN_CRM:
        if (memcmp(&context->running_data.a->log_msg.msg_crm, &msg->msg.crm, sizeof(msg->msg.crm)) != 0)
        {
            memcpy(&context->running_data.a->log_msg.msg_crm, &msg->msg.crm, sizeof(msg->msg.crm));
            return true;
        }
        return false;

    case OPENCHAOJI_GBT27930_A_PGN_CTS:
        if (memcmp(&context->running_data.a->log_msg.msg_cts, &msg->msg.cts, sizeof(msg->msg.cts)) != 0)
        {
            memcpy(&context->running_data.a->log_msg.msg_cts, &msg->msg.cts, sizeof(msg->msg.cts));
            return true;
        }
        return false;

    case OPENCHAOJI_GBT27930_A_PGN_CML:
        if (memcmp(&context->running_data.a->log_msg.msg_cml, &msg->msg.cml, sizeof(msg->msg.cml)) != 0)
        {
            memcpy(&context->running_data.a->log_msg.msg_cml, &msg->msg.cml, sizeof(msg->msg.cml));
            return true;
        }
        return false;

    case OPENCHAOJI_GBT27930_A_PGN_CRO:
        if (memcmp(&context->running_data.a->log_msg.msg_cro, &msg->msg.cro, sizeof(msg->msg.cro)) != 0)
        {
            memcpy(&context->running_data.a->log_msg.msg_cro, &msg->msg.cro, sizeof(msg->msg.cro));
            return true;
        }
        return false;

    case OPENCHAOJI_GBT27930_A_PGN_CCS:
        if (memcmp(&context->running_data.a->log_msg.msg_ccs, &msg->msg.ccs, sizeof(msg->msg.ccs)) != 0)
        {
            memcpy(&context->running_data.a->log_msg.msg_ccs, &msg->msg.ccs, sizeof(msg->msg.ccs));
            return true;
        }
        return false;

    case OPENCHAOJI_GBT27930_A_PGN_CST:
        if (memcmp(&context->running_data.a->log_msg.msg_cst, &msg->msg.cst, sizeof(msg->msg.cst)) != 0)
        {
            memcpy(&context->running_data.a->log_msg.msg_cst, &msg->msg.cst, sizeof(msg->msg.cst));
            return true;
        }
        return false;

    case OPENCHAOJI_GBT27930_A_PGN_CSD:
        if (memcmp(&context->running_data.a->log_msg.msg_csd, &msg->msg.csd, sizeof(msg->msg.csd)) != 0)
        {
            memcpy(&context->running_data.a->log_msg.msg_csd, &msg->msg.csd, sizeof(msg->msg.csd));
            return true;
        }
        return false;

    case OPENCHAOJI_GBT27930_A_PGN_CEM:
        if (memcmp(&context->running_data.a->log_msg.msg_cem, &msg->msg.cem, sizeof(msg->msg.cem)) != 0)
        {
            memcpy(&context->running_data.a->log_msg.msg_cem, &msg->msg.cem, sizeof(msg->msg.cem));
            return true;
        }
        return false;

    case OPENCHAOJI_GBT27930_A_PGN_BHM:
        if (memcmp(&context->running_data.a->log_msg.msg_bhm, &msg->msg.bhm, sizeof(msg->msg.bhm)) != 0)
        {
            memcpy(&context->running_data.a->log_msg.msg_bhm, &msg->msg.bhm, sizeof(msg->msg.bhm));
            return true;
        }
        return false;

    case OPENCHAOJI_GBT27930_A_PGN_BRM:
        if (memcmp(&context->running_data.a->log_msg.msg_brm, &msg->msg.brm, sizeof(msg->msg.brm)) != 0)
        {
            memcpy(&context->running_data.a->log_msg.msg_brm, &msg->msg.brm, sizeof(msg->msg.brm));
            return true;
        }
        return false;

    case OPENCHAOJI_GBT27930_A_PGN_BCP:
        if (memcmp(&context->running_data.a->log_msg.msg_bcp, &msg->msg.bcp, sizeof(msg->msg.bcp)) != 0)
        {
            memcpy(&context->running_data.a->log_msg.msg_bcp, &msg->msg.bcp, sizeof(msg->msg.bcp));
            return true;
        }
        return false;

    case OPENCHAOJI_GBT27930_A_PGN_BRO:
        if (memcmp(&context->running_data.a->log_msg.msg_bro, &msg->msg.bro, sizeof(msg->msg.bro)) != 0)
        {
            memcpy(&context->running_data.a->log_msg.msg_bro, &msg->msg.bro, sizeof(msg->msg.bro));
            return true;
        }
        return false;

    case OPENCHAOJI_GBT27930_A_PGN_BCL:
        if (memcmp(&context->running_data.a->log_msg.msg_bcl, &msg->msg.bcl, sizeof(msg->msg.bcl)) != 0)
        {
            memcpy(&context->running_data.a->log_msg.msg_bcl, &msg->msg.bcl, sizeof(msg->msg.bcl));
            return true;
        }
        return false;

    case OPENCHAOJI_GBT27930_A_PGN_BCS:
        if (memcmp(&context->running_data.a->log_msg.msg_bcs, &msg->msg.bcs, sizeof(msg->msg.bcs)) != 0)
        {
            memcpy(&context->running_data.a->log_msg.msg_bcs, &msg->msg.bcs, sizeof(msg->msg.bcs));
            return true;
        }
        return false;

    case OPENCHAOJI_GBT27930_A_PGN_BSM:
        if (memcmp(&context->running_data.a->log_msg.msg_bsm, &msg->msg.bsm, sizeof(msg->msg.bsm)) != 0)
        {
            memcpy(&context->running_data.a->log_msg.msg_bsm, &msg->msg.bsm, sizeof(msg->msg.bsm));
            return true;
        }
        return false;

    case OPENCHAOJI_GBT27930_A_PGN_BMV:
        if (memcmp(&context->running_data.a->log_msg.msg_bmv, &msg->msg.bmv, sizeof(msg->msg.bmv)) != 0)
        {
            memcpy(&context->running_data.a->log_msg.msg_bmv, &msg->msg.bmv, sizeof(msg->msg.bmv));
            return true;
        }
        return false;

    case OPENCHAOJI_GBT27930_A_PGN_BMT:
        if (memcmp(&context->running_data.a->log_msg.msg_bmt, &msg->msg.bmt, sizeof(msg->msg.bmt)) != 0)
        {
            memcpy(&context->running_data.a->log_msg.msg_bmt, &msg->msg.bmt, sizeof(msg->msg.bmt));
            return true;
        }
        return false;

    case OPENCHAOJI_GBT27930_A_PGN_BSP:
        if (memcmp(&context->running_data.a->log_msg.msg_bsp, &msg->msg.bsp, sizeof(msg->msg.bsp)) != 0)
        {
            memcpy(&context->running_data.a->log_msg.msg_bsp, &msg->msg.bsp, sizeof(msg->msg.bsp));
            return true;
        }
        return false;

    case OPENCHAOJI_GBT27930_A_PGN_BST:
        if (memcmp(&context->running_data.a->log_msg.msg_bst, &msg->msg.bst, sizeof(msg->msg.bst)) != 0)
        {
            memcpy(&context->running_data.a->log_msg.msg_bst, &msg->msg.bst, sizeof(msg->msg.bst));
            return true;
        }
        return false;

    case OPENCHAOJI_GBT27930_A_PGN_BSD:
        if (memcmp(&context->running_data.a->log_msg.msg_bsd, &msg->msg.bsd, sizeof(msg->msg.bsd)) != 0)
        {
            memcpy(&context->running_data.a->log_msg.msg_bsd, &msg->msg.bsd, sizeof(msg->msg.bsd));
            return true;
        }
        return false;

    case OPENCHAOJI_GBT27930_A_PGN_BEM:
        if (memcmp(&context->running_data.a->log_msg.msg_bem, &msg->msg.bem, sizeof(msg->msg.bem)) != 0)
        {
            memcpy(&context->running_data.a->log_msg.msg_bem, &msg->msg.bem, sizeof(msg->msg.bem));
            return true;
        }
        return false;

    default: return false;
    }
}

// 通用报文发送
static int OpenChaoJi_gbt27930_a_secc_send_normal(struct OpenChaoJi_secc_context * context, uint32_t all, uint8_t *data ,uint16_t data_len)       // 数据发送
{
    struct OpenChaoJi_utility_data_buff_send_data send_data;
    send_data.tag.all = all;
    send_data.cnt = SEND_NORMAL_CNT_MACRO;
    send_data.interval_ms = SEND_NORMAL_INTERVAL_MS_MACRO;

    struct OpenChaoJi_gbt27930_a_msg msg;
    msg.pid = send_data.tag.gbt.pf;
    memcpy(&msg.msg, data, data_len);

 #if 0
    send_data.send_data.src_free = SEND_NORMAL_SRC_FREE_MACRO;
    send_data.send_data.data = data;
    send_data.send_data.len = data_len;
#else
    int dynamic_data_len = 0;
    unsigned char * dynamic_data = OpenChaoJi_gbt27930_a_msg_encode_data(&msg, &dynamic_data_len);
    if (dynamic_data == NULL)
    {
        return 0;
    }
    send_data.send_data.src_free = 0;
    send_data.send_data.data = dynamic_data;
    send_data.send_data.len = dynamic_data_len;
#endif

    bool changed = OpenChaoJi_gbt27930_a_secc_log_msg_set(context, &msg);

    // 发送数据发生变化必须打出完整报文, 打印级别是INFO则把所有报文打印出来
    if ((changed) || ((OpenChaoJi_debug_get_log_level() & DBGL_INFO) != 0))
    {
        // 周期性报文, 即使INFO级别也不打印, 只变化才打印
        if (!changed && !s_gbt_a_public_debug_enable)
        {
            goto SEND_DATA;
        }

        OpenChaoJi_gbt27930_a_msg_log(&msg);
        if ((OpenChaoJi_debug_get_log_level() & DBGL_INFO) != 0)
        {
            LOG_DATA_CHANGE("->[%02X][%d]", msg.pid, send_data.send_data.len);
            LOG_DATA_BUFF_CHANGE(send_data.send_data.data, send_data.send_data.len);
        }
    }

SEND_DATA:
    return OpenChaoJi_secc_utility_session_data_write(context->context_session, &send_data);
}

/* -------------- 通用功能 国网 -------------- */

/* 格式转换, HEX转BCD */
static uint8_t OpenChaoJi_gbt27930_a_secc_hex_to_bcd(uint8_t hex)
{
    return ((hex / 10) << 4) + (hex % 10);
}

/* 预充电 */
enum OpenChaoJi_gbt27930_a_secc_precharge_stauts {
    OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_INIT = 0,          // 初始化
    OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_CHECK_VENT_OFF,    // 确认泄放电路已切除
    OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_WAIT_EVCC_VOLTAGE, // 延时检测，等待车辆接口电压稳定
    OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_CHECK_VOLTAGE,     // 校验车辆接口当前电压
    OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_START_MODULE,      // 启动模块输出
    OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_CLOSE_C1_C2,       // 闭合C1 C2
    OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_FINISHED,          // 预充完成
    OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_ERROR              // 预充故障
};

// 预充电
static int OpenChaoJi_gbt27930_a_secc_pre_charge(struct OpenChaoJi_secc_context * context, int msg_measured_voltage)
{
    struct OpenChaoJi_secc_hal_samp samp_value;

    if (context->running_data.a->precharge_status == OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_INIT)
    {
        LOG_DEBUG("[%d]precharge: init", context->tag);
        // 开启延迟检测继电器外侧电压定时器(等待充电口电压稳定)
        OpenChaoJi_os_soft_timer_start(&context->running_data.a->tco_precharge, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_PRECHG_EVCC_VOL);
        // 预充前, 确认泄放电路已切除
        OpenChaoJi_secc_hal_vent_request_stop(context->hal_handle);
        context->running_data.a->precharge_status = OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_CHECK_VENT_OFF;
    }
    else if (context->running_data.a->precharge_status == OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_CHECK_VENT_OFF)
    {
        // 泄放已切除
        if (!OpenChaoJi_secc_hal_gbt_a_is_closed_vent_relay(context->hal_handle))
        {
            LOG_DEBUG("[%d]precharge: vent is off", context->tag);
            context->running_data.a->precharge_status = OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_WAIT_EVCC_VOLTAGE;
        }
        // 泄放继电器断开超时
        if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_precharge))
        {
            LOG_ERR("[%d]precharge: vent off timeout", context->tag);
            context->running_data.a->precharge_status = OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_ERROR;
        }
    }
    else if (context->running_data.a->precharge_status == OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_WAIT_EVCC_VOLTAGE)
    {
        LOG_DEBUG("[%d]precharge: wait evcc voltage", context->tag);
        // 延时结束, 开始继电器外侧电压检测
        if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_precharge))
        {
            LOG_DEBUG("[%d]precharge: start to run", context->tag);
            // 重新置位预充超时定时器
            OpenChaoJi_os_soft_timer_start(&context->running_data.a->tco_precharge, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_PRECHG);
            context->running_data.a->precharge_status = OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_CHECK_VOLTAGE;
        }
    }
    else if (context->running_data.a->precharge_status == OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_CHECK_VOLTAGE)
    {
        if (context->current_module_status_id < OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S0_INIT) // 充电前（准备就绪过程中）
        {
            int pre_deviation = 100;
            // 获取接触器C1 C2电压
            OpenChaoJi_secc_hal_sampling_value(context->hal_handle, &samp_value);
            LOG_DEBUG("[%d]precharge: voltage_out=%d, msg_measured_voltage=%d", context->tag, samp_value.voltage_out, msg_measured_voltage);
            // 判断C1C2外侧电压与通信报文电池电压误差5%以内且在充电机正常工作电压范围 (暂停充电恢复时不判该条件)
            if (msg_measured_voltage > 0)
            {
                pre_deviation = (msg_measured_voltage - samp_value.voltage_out) * 100 / msg_measured_voltage;
            }

            // 电压误差百分之5以内且电池电压在正常范围
            if ((-5 <= pre_deviation) && (pre_deviation <= 5)    && \
                (samp_value.voltage_out < context->running_data.a->msg_cml.max_output_voltage) && \
                (samp_value.voltage_out > context->running_data.a->msg_cml.min_output_voltage))
            {
                // 设置模块电压
                LOG_INFO("[%d]precharge: voltage check ok, start module, output_voltage=%d", context->tag, samp_value.voltage_out - 50);
                OpenChaoJi_secc_hal_power_module_request_start(context->hal_handle, samp_value.voltage_out - 50, 4000 - context->running_data.a->msg_cml.min_output_current);
                context->running_data.a->precharge_status = OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_START_MODULE;
            }
            else
            {
                LOG_ERR("[%d]precharge: evcc voltage error", context->tag);
                // 是否判定故障退出
                // context->running_data.a->precharge_status = OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_ERROR;
            }
        }
        else // 充电中（暂停阶段恢复充电）
        {
            // 获取接触器C1 C2电压
            OpenChaoJi_secc_hal_sampling_value(context->hal_handle, &samp_value);
            LOG_DEBUG("[%d]precharge: voltage_out=%d", context->tag, samp_value.voltage_out);

            // 设置模块电压 (暂停充电过程中, EVCC电池电压不会切断)
            LOG_INFO("[%d]precharge: start module, output_voltage=%d", context->tag, samp_value.voltage_out - 50);
            OpenChaoJi_secc_hal_power_module_request_start(context->hal_handle, samp_value.voltage_out - 50, 4000 - context->running_data.a->msg_cml.min_output_current);
            context->running_data.a->precharge_status = OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_START_MODULE;
        }
    }
    else if (context->running_data.a->precharge_status == OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_START_MODULE)
    {
        // 车辆供电回路电压正常
        OpenChaoJi_secc_hal_sampling_value(context->hal_handle, &samp_value);
        LOG_DEBUG("[%d]precharge: voltage_out=%d, voltage_in=%d", context->tag, samp_value.voltage_out, samp_value.voltage_in);
        if ((samp_value.voltage_out - 100) <= (samp_value.voltage_in))
        {
            // 闭合C1 C2
            LOG_NOTICE("[%d]precharge: close C1 C2", context->tag);
            OpenChaoJi_secc_hal_gbt_close_dc_relay(context->hal_handle, 1);
            context->running_data.a->precharge_status = OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_CLOSE_C1_C2;
        }
    }
    else if (context->running_data.a->precharge_status == OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_CLOSE_C1_C2)
    {
        // 确认C1 C2闭合状态
        if (OpenChaoJi_secc_hal_get_status_dc_relay(context->hal_handle) == OPENCHAOJI_SECC_HAL_DC_RELAY_C1C2_ALL_CLOSE) // C1 C2闭合
        {
            LOG_NOTICE("[%d]precharge: C1 C2 closed, precharge finished", context->tag);
            context->running_data.a->precharge_status = OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_FINISHED;
        }
    }

    if ((context->running_data.a->precharge_status >= OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_CHECK_VOLTAGE) && \
        (context->running_data.a->precharge_status < OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_FINISHED))
    {
        // 预充超时判断
        if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_precharge))
        {
            LOG_ERR("[%d]precharge: timeout", context->tag);
            context->running_data.a->precharge_status = OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_ERROR;
        }
    }

    return context->running_data.a->precharge_status;
}


/* 停机泄放 */
enum OpenChaoJi_gbt27930_a_secc_stopping_stauts {
    OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_INIT = 0,            // 初始化
    OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_SHUTDOWN_MODULE,     // 模块关机(降电流)
    OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_CUT_OFF_C1_C2,       // 断开C1 C2
    OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_VENT_START,          // 投泄放
    OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_VENT_STOP,           // 泄放停止
    OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_CUT_OFF_C5_C6,       // 等待电池切断(外侧电压小于60V)
    OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_FINISHED,            // 停机完成
    OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_ERROR                // 停机故障
};

// 停机泄放
static int OpenChaoJi_gbt27930_a_secc_stopping(struct OpenChaoJi_secc_context * context)
{
    struct OpenChaoJi_secc_hal_samp samp_value;
    if (context->running_data.a->stop_status == OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_INIT)
    {
        // 设置模块关机
        LOG_NOTICE("[%d]stopping: shutdown module", context->tag);
        OpenChaoJi_secc_hal_power_module_request_stop(context->hal_handle);
        // 开启停机超时定时器, 超时时间由外部传入 stop_ticks
        LOG_INFO("[%d]stopping: start module timer", context->tag);
        OpenChaoJi_os_soft_timer_start(&context->running_data.a->tco_stopping, context->running_data.a->stop_ticks);
        context->running_data.a->stop_status = OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_SHUTDOWN_MODULE;
    }
    else if (context->running_data.a->stop_status == OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_SHUTDOWN_MODULE)
    {
        OpenChaoJi_secc_hal_sampling_value(context->hal_handle, &samp_value);
        LOG_DEBUG("[%d]stopping: current=%d", context->tag, samp_value.current);
        // 由于无法获取模块状态, 目前只能以电流降至5A及以下, 认为模块停机完成 (增加超时判断)
        if (samp_value.current <= 50 || OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_stopping))
        {
            // 断开C1 C2
            LOG_NOTICE("[%d]stopping: module stopped, cut off C1 C2", context->tag);
            OpenChaoJi_secc_hal_gbt_close_dc_relay(context->hal_handle, 0);
            // 启动定时器, 用于C1 C2断开动作超时检测
            LOG_INFO("[%d]stopping: start C1 C2 timer", context->tag);
            OpenChaoJi_os_soft_timer_start(&context->running_data.a->tco_stopping, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_RELAY);
            context->running_data.a->stop_status = OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_CUT_OFF_C1_C2;
        }
    }
    else if (context->running_data.a->stop_status == OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_CUT_OFF_C1_C2)
    {
        // 等待C1C2断开
        if (OpenChaoJi_secc_hal_get_status_dc_relay(context->hal_handle) == OPENCHAOJI_SECC_HAL_DC_RELAY_C1C2_ALL_OPEN)
        {
            // 投泄放
            LOG_NOTICE("[%d]stopping: C1 C2 already cut off, start vent", context->tag);
            OpenChaoJi_secc_hal_vent_request_start(context->hal_handle);
            // 启动定时器, 用于泄放超时检测
            LOG_INFO("[%d]stopping: start vent timer", context->tag);
            OpenChaoJi_os_soft_timer_start(&context->running_data.a->tco_stopping, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_VENT);
            context->running_data.a->stop_status = OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_VENT_START;
        }
        else
        {
            LOG_DEBUG("[%d]stopping: cut off C1 C2 (again)", context->tag);
            OpenChaoJi_secc_hal_gbt_close_dc_relay(context->hal_handle, 0);
            // C1 C2断开超时判断
            if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_stopping))
            {
                // C1 C2断开超时, 故障
                LOG_ERR("[%d]stopping: cut off C1 C2 failed", context->tag);
                context->running_data.a->stop_status = OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_ERROR;
            }
        }
    }
    // 泄放进行中
    else if (context->running_data.a->stop_status == OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_VENT_START)
    {
        // 等待内侧电压下降
        OpenChaoJi_secc_hal_sampling_value(context->hal_handle,&samp_value);
        LOG_DEBUG("[%d]stopping: voltage_in=%d", context->tag, samp_value.voltage_in);
        if ((samp_value.voltage_in < 600) || OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_stopping))
        {
            // 泄放超时
            if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_stopping))
                LOG_ERR("[%d]stopping: vent timeout", context->tag);

            // 切除泄放
            LOG_NOTICE("[%d]stopping: stop vent", context->tag);
            OpenChaoJi_secc_hal_vent_request_stop(context->hal_handle);
            // 启动定时器, 用于泄放继电器断开动作超时检测
            LOG_INFO("[%d]stopping: start vent_off timer", context->tag);
            OpenChaoJi_os_soft_timer_start(&context->running_data.a->tco_stopping, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_RELAY);
            context->running_data.a->stop_status = OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_VENT_STOP;
        }
    }
    else if (context->running_data.a->stop_status == OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_VENT_STOP)
    {
        LOG_DEBUG("[%d]stopping: vent stopping...", context->tag);

        // 泄放切除状态判断
        if (!OpenChaoJi_secc_hal_gbt_a_is_closed_vent_relay(context->hal_handle))
        {
            // 泄放已切除, 等待外侧电压下降
            LOG_NOTICE("[%d]stopping: vent stopped, secc stopped", context->tag);
            context->running_data.a->stop_status = OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_CUT_OFF_C5_C6;
        }
        else if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_stopping))
        {
            // 泄放切除超时, 故障
            LOG_ERR("[%d]stopping: vent stop timeout", context->tag);
            context->running_data.a->stop_status = OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_ERROR;
        }
    }
    else if (context->running_data.a->stop_status == OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_CUT_OFF_C5_C6)
    {
        // 等待外侧电压下降
        OpenChaoJi_secc_hal_sampling_value(context->hal_handle,&samp_value);
        LOG_DEBUG("[%d]stopping: voltage_out=%d", context->tag, samp_value.voltage_out);
        if (samp_value.voltage_out < 600)
        {
            // 停机完成, 外侧电池已断开
            LOG_NOTICE("[%d]stopping: evcc stopped, batt cut off", context->tag);
            context->running_data.a->stop_status = OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_FINISHED;
        }
    }
    return context->running_data.a->stop_status;
}

static int OpenChaoJi_gbt27930_a_secc_stop_normal(struct OpenChaoJi_secc_context * context, uint8_t end_code, uint8_t end_reason) // 正常停机
{
    LOG_NOTICE("[%d]NormalStopCharge: code=%02x, reason=%02x", context->tag, end_code, end_reason);

    // 设置模块关机
    OpenChaoJi_secc_hal_power_module_request_stop(context->hal_handle);

    // 解析停机代码 // TODO: 故障码定义、CST映射
    if (end_code == OPENCHAOJI_GBT27930_A_END_CODE_SECC_NORMAL)
    {
        switch (end_reason)
        {
            case OPENCHAOJI_GBT27930_A_END_REASON_SECC_NORMAL_FINISHED:
                context->running_data.a->msg_cst.stop_code.bits.condition_reached_suspends = 0x01; // 达到充电机设定的条件中止
                break;
            case OPENCHAOJI_GBT27930_A_END_REASON_SECC_NORMAL_USER:
                context->running_data.a->msg_cst.stop_code.bits.artificial_suspends = 0x01;        // 人工中止
                break;
            case OPENCHAOJI_GBT27930_A_END_REASON_SECC_NORMAL_BST:
                context->running_data.a->msg_cst.stop_code.bits.bms_actively_suspends = 0x01;      // 车辆主动中止
                break;
            default:
                context->running_data.a->msg_cst.stop_code.bits.fault_suspends = 0x01;             // 故障中止
                context->running_data.a->msg_cst.fault_code.bits.other_fault = 0x01;               // 其他故障
                break;
        }
    }
    else // 停机码异常, 非正常停机
    {
        context->running_data.a->msg_cst.stop_code.bits.fault_suspends = 0x01; // 故障中止
        context->running_data.a->msg_cst.fault_code.bits.other_fault = 0x01;    // 其他故障
    }

    if (end_reason == OPENCHAOJI_GBT27930_A_END_REASON_SECC_NORMAL_BST)
    {
        // 车辆主动停止, 进入停机结束阶段
        LOG_NOTICE("[%d]NormalStopCharge To Charge S6", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S6_STOPPED;
    }
    else
    {
        // 充电机主动停止, 等待车辆进入停机阶段
        LOG_NOTICE("[%d]NormalStopCharge To Charge S5", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S5_EV_STOP;
    }
}

static int OpenChaoJi_gbt27930_a_secc_stop_failed(struct OpenChaoJi_secc_context * context, uint8_t end_code, uint8_t end_reason) // 故障停机
{
    LOG_ERR("[%d]ErrStopCharge: code=%02x, reason=%02x", context->tag, end_code, end_reason);

    // 设置模块关机
    OpenChaoJi_secc_hal_power_module_request_stop(context->hal_handle);

    // 解析停机代码 // TODO: 故障码定义、CST映射
    if (end_code == OPENCHAOJI_GBT27930_A_END_CODE_SECC_FAULT)
    {
        context->running_data.a->msg_cst.stop_code.bits.fault_suspends = 0x01;                      // 故障中止
        switch (end_reason)
        {
            case OPENCHAOJI_GBT27930_A_END_REASON_SECC_FAULT_EMERGENCY:
                context->running_data.a->msg_cst.fault_code.bits.emergency_stop = 0x01;             // 急停故障
                break;
            case OPENCHAOJI_GBT27930_A_END_REASON_SECC_FAULT_SELFCHECK:
                context->running_data.a->msg_cst.fault_code.bits.self_check_fault = 0x01;           // 自检故障
                break;
            case OPENCHAOJI_GBT27930_A_END_REASON_SECC_FAULT_PRECHARGE:
                context->running_data.a->msg_cst.fault_code.bits.precharging_fault = 0x01;          // 预充故障
                break;
            case OPENCHAOJI_GBT27930_A_END_REASON_SECC_FAULT_CC1:
                context->running_data.a->msg_cst.fault_code.bits.other_fault = 0x01;                // 其他故障
                break;
            case OPENCHAOJI_GBT27930_A_END_REASON_SECC_FAULT_LOCK:
                context->running_data.a->msg_cst.fault_code.bits.other_fault = 0x01;                // 其他故障
                break;
            default:
                context->running_data.a->msg_cst.fault_code.bits.other_fault = 0x01;                // 其他故障
                break;
        }
    }
    else if (end_code == OPENCHAOJI_GBT27930_A_END_CODE_SECC_ERROR)
    {
        context->running_data.a->msg_cst.stop_code.bits.fault_suspends = 0x01;                      // 故障中止
        switch (end_reason)
        {
            case OPENCHAOJI_GBT27930_A_END_REASON_SECC_ERROR_VOLTAGE:
                context->running_data.a->msg_cst.error_code.bits.voltage_abnormal_error = 0x01;     // 电压异常
                break;
            case OPENCHAOJI_GBT27930_A_END_REASON_SECC_ERROR_CURRENT:
                context->running_data.a->msg_cst.error_code.bits.current_mismatch_error = 0x01;     // 电流不匹配
                break;
            case OPENCHAOJI_GBT27930_A_END_REASON_SECC_ERROR_PARAM:
                context->running_data.a->msg_cst.error_code.bits.param_mismatch_error = 0x01;       // 充电参数不匹配
                break;
            default:
                context->running_data.a->msg_cst.fault_code.bits.other_fault = 0x01;                // 其他故障
                break;
        }
    }
    else // 停机码异常, 非正常停机
    {
        context->running_data.a->msg_cst.stop_code.bits.fault_suspends = 0x01;  // 故障中止
        context->running_data.a->msg_cst.fault_code.bits.other_fault = 0x01;    // 其他故障
    }

    // 充电机主动停止, 等待车辆进入停机阶段
    LOG_ERR("[%d]ErrStopCharge To Charge S5", context->tag);
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S5_EV_STOP;
}

static int OpenChaoJi_gbt27930_a_secc_stop_emergency(struct OpenChaoJi_secc_context * context, uint8_t end_code, uint8_t end_reason) // 紧急停机
{
    LOG_ERR("[%d]EmergencyStopCharge: code=%02x, reason=%02x", context->tag, end_code, end_reason);

    // 设置模块关机
    OpenChaoJi_secc_hal_power_module_request_stop(context->hal_handle);

    if (end_code == OPENCHAOJI_GBT27930_A_END_CODE_SECC_FAULT && \
        end_reason == OPENCHAOJI_GBT27930_A_END_REASON_SECC_FAULT_EMERGENCY)
    {
        context->running_data.a->msg_cst.stop_code.bits.fault_suspends = 0x01; // 故障中止
        context->running_data.a->msg_cst.fault_code.bits.emergency_stop = 0x01; // 急停故障
    }
    else // 停机码异常, 非正常停机
    {
        context->running_data.a->msg_cst.stop_code.bits.fault_suspends = 0x01; // 故障中止
        context->running_data.a->msg_cst.fault_code.bits.other_fault = 0x01;    // 其他故障
    }

    // 充电机主动停止, 等待车辆进入停机阶段
    LOG_ERR("[%d]EmergencyStopCharge To Charge S5", context->tag);
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S5_EV_STOP;
}

static int OpenChaoJi_gbt27930_a_secc_rcvd_bem(struct OpenChaoJi_secc_context * context) // 收到车辆BEM报文
{
    // 设置模块关机
    OpenChaoJi_secc_hal_power_module_request_stop(context->hal_handle);

    // 进入超时处理阶段
    LOG_ERR("[%d]BEM To Error S0", context->tag);
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_ERROR_S0_INIT;
}

/* -------------- IDLE 模块 特来电 -------------- */
static void OpenChaoJi_gbt27930_a_secc_prev_idle_s0_idle(struct OpenChaoJi_secc_context * context)
{
    OpenChaoJi_gbt27930_a_secc_reset_to_default(context);
}
static void OpenChaoJi_gbt27930_a_secc_post_idle_s0_idle(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_idle_s0_idle(struct OpenChaoJi_secc_context * context)
{
    if (context->app_permit_charge)   // 18487.B.4.2, 连接确认
    {
        LOG_NOTICE("[%d]Idle S0, app permit charge", context->tag);
        // 数据缓存初始化
        // memset(context->running_data.a, 0, sizeof(struct OpenChaoJi_secc_gbt27930_a_data));
        LOG_NOTICE("[%d]Idle S0 To Trigger S0", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_TRIGGER_S0_CONNECT_CONFIRM;
    }

    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_IDLE_S0_IDLE;
}

const struct OpenChaoJi_secc_module_status c_sytem_a_secc_status_array_idle[OPENCHAOJI_GBT27930_A_SECC_STATUS_IDLE_NUM] = {
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_IDLE_S0_IDLE,
        .name = "Idle.S0.Idle",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_idle_s0_idle,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_idle_s0_idle,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_idle_s0_idle,
    },
};

const struct OpenChaoJi_secc_module c_gbt27930_a_secc_module_idle =
{
    .module_id = OPENCHAOJI_GBT27930_A_MODULE_IDLE,
    .name = "Idle",
    .status_array = c_sytem_a_secc_status_array_idle,
    .status_array_len = OPENCHAOJI_GBT27930_A_SECC_STATUS_IDLE_NUM,
};



/* -------------- Trigger 模块 特来电 -------------- */
static void OpenChaoJi_gbt27930_a_secc_prev_trigger_s0_connect_confirm(struct OpenChaoJi_secc_context * context) {}
static void OpenChaoJi_gbt27930_a_secc_post_trigger_s0_connect_confirm(struct OpenChaoJi_secc_context * context)
{
    // 电子锁上锁
    LOG_NOTICE("Trigger S0 close lock");
    OpenChaoJi_secc_hal_gbt_a_lock(context->hal_handle, 1);

    // 开启电子锁闭合状态超时定时器
    LOG_DEBUG("[%d]Trigger S0 start lock timer", context->tag);
    OpenChaoJi_os_soft_timer_start(&context->running_data.a->tco_lock, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_RELAY);
}
static int  OpenChaoJi_gbt27930_a_secc_loop_trigger_s0_connect_confirm(struct OpenChaoJi_secc_context * context)
{
    if (OpenChaoJi_secc_utility_pilot_is_evcc_connected(context->context_pilot))   // 18487.B.4.2, 连接确认
    {
        LOG_NOTICE("[%d]Trigger S0 To S1", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_TRIGGER_S1_LOCK_CONFIRM;
    }

    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_TRIGGER_S0_CONNECT_CONFIRM;
}

static void OpenChaoJi_gbt27930_a_secc_prev_trigger_s1_lock_confirm(struct OpenChaoJi_secc_context * context) {}
static void OpenChaoJi_gbt27930_a_secc_post_trigger_s1_lock_confirm(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_trigger_s1_lock_confirm(struct OpenChaoJi_secc_context * context)
{
    if (OpenChaoJi_secc_hal_gbt_a_is_locked(context->hal_handle))   // 电子锁确认
    {
        // 闭合辅源
        LOG_NOTICE("Trigger S1 close aux");
        OpenChaoJi_secc_hal_gbt_a_close_aux_power(context->hal_handle, 1);

        // 开启辅助电源闭合超时定时器
        LOG_DEBUG("[%d]Trigger S1 start aux_power timer", context->tag);
        OpenChaoJi_os_soft_timer_start(&context->running_data.a->tco_auxpower, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_RELAY);

        LOG_NOTICE("[%d]Trigger S1 To S2", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_TRIGGER_S2_AUX_CONFIRM;
    }

    // 等待电子锁闭合状态超时
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_lock))
    {
        LOG_ERR("[%d]Trigger S1 lock timeout", context->tag);

        // 电子锁解锁
        LOG_NOTICE("[%d]Trigger S1 release elock", context->tag);
        OpenChaoJi_secc_hal_gbt_a_lock(context->hal_handle, 0);

        // 复位充电启动标识
        context->app_permit_charge = 0;

        // 退出充电
        LOG_NOTICE("[%d]Trigger S1 Return to Idle", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_IDLE_S0_IDLE;
    }

    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_TRIGGER_S1_LOCK_CONFIRM;
}

static void OpenChaoJi_gbt27930_a_secc_prev_trigger_s2_aux_confirm(struct OpenChaoJi_secc_context * context) {}
static void OpenChaoJi_gbt27930_a_secc_post_trigger_s2_aux_confirm(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_trigger_s2_aux_confirm(struct OpenChaoJi_secc_context * context)
{
    if (OpenChaoJi_secc_hal_gbt_a_is_closed_aux_power(context->hal_handle))   // 辅源确认
    {
        LOG_NOTICE("[%d]Trigger S2 To Handshake S0", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_HANDSHAKE_S0_INIT;
    }

    // 等待辅助电源闭合状态超时
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_auxpower))
    {
        LOG_ERR("[%d]Trigger S2 aux_power timeout", context->tag);

        // 断开辅助电源
        LOG_NOTICE("[%d]Trigger S2 cut off S3 S4", context->tag);
        OpenChaoJi_secc_hal_gbt_a_close_aux_power(context->hal_handle, 0);

        // 电子锁解锁
        LOG_NOTICE("[%d]Trigger S2 release elock", context->tag);
        OpenChaoJi_secc_hal_gbt_a_lock(context->hal_handle, 0);

        // 复位充电启动标识
        context->app_permit_charge = 0;

        // 退出充电
        LOG_NOTICE("[%d]Trigger S2 Return to Idle", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_IDLE_S0_IDLE;
    }

    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_TRIGGER_S2_AUX_CONFIRM;
}

const struct OpenChaoJi_secc_module_status c_sytem_a_secc_status_array_trigger[OPENCHAOJI_GBT27930_A_SECC_STATUS_TRIGGER_NUM] = {
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_TRIGGER_S0_CONNECT_CONFIRM,
        .name = "Trigger.S0.Connect.Confirm",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_trigger_s0_connect_confirm,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_trigger_s0_connect_confirm,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_trigger_s0_connect_confirm,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_TRIGGER_S1_LOCK_CONFIRM,
        .name = "Trigger.S1.Lock.Confirm",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_trigger_s1_lock_confirm,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_trigger_s1_lock_confirm,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_trigger_s1_lock_confirm,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_TRIGGER_S2_AUX_CONFIRM,
        .name = "Trigger.S2.Aux.Confirm",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_trigger_s2_aux_confirm,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_trigger_s2_aux_confirm,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_trigger_s2_aux_confirm,
    },
};

const struct OpenChaoJi_secc_module c_gbt27930_a_secc_module_trigger =
{
    .module_id = OPENCHAOJI_GBT27930_A_MODULE_TRIGGER,
    .name = "Trigger",
    .status_array = c_sytem_a_secc_status_array_trigger,
    .status_array_len = OPENCHAOJI_GBT27930_A_SECC_STATUS_TRIGGER_NUM,
};

/* -------------- 充电握手 模块 国网 -------------- */

static void OpenChaoJi_gbt27930_a_secc_prev_handshake_s0_init(struct OpenChaoJi_secc_context * context)
{
    LOG_NOTICE("[%d]Handshake Status Start", context->tag);
    LOG_NOTICE("[%d]Handshake S0 init", context->tag);
    // 初始化
    context->running_data.a->protocol_version = OPENCHAOJI_GBT27930_A_PROTOCOL_VERSION_TYPE_MAKE(1,1,0);
    context->running_data.a->stop_ticks = OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_STOP_NORMAL(0);
    context->running_data.a->stop_status = OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_INIT;
    context->running_data.a->precharge_status = OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_INIT;
    context->running_data.a->msg_bem_ok = 0;
    memset(&context->running_data.a->handshake, 0, sizeof(context->running_data.a->handshake));
    // CST
    memset(&context->running_data.a->msg_cst, 0, sizeof(struct OpenChaoJi_gbt27930_a_msg_cst));
    // CEM
    memset(&context->running_data.a->msg_cem, 0, sizeof(struct OpenChaoJi_gbt27930_a_msg_cem));
    context->running_data.a->msg_cem.tout_code.all = 0xF0C0F0FC;
    // CHM
    context->running_data.a->msg_chm.pro_version[0] = OPENCHAOJI_GBT27930_A_PROTOCOL_VERSION_TYPE_MAJOR(OPENCHAOJI_GBT27930_A_PROTOCOL_VERSION_TYPE_1_1_0); // 充电机通信协议版本号, 当前版本为 V1.1
    context->running_data.a->msg_chm.pro_version[1] = OPENCHAOJI_GBT27930_A_PROTOCOL_VERSION_TYPE_MINOR(OPENCHAOJI_GBT27930_A_PROTOCOL_VERSION_TYPE_1_1_0);
    context->running_data.a->msg_chm.pro_version[2] = OPENCHAOJI_GBT27930_A_PROTOCOL_VERSION_TYPE_TMP(OPENCHAOJI_GBT27930_A_PROTOCOL_VERSION_TYPE_1_1_0);
    // CRM
    context->running_data.a->msg_crm.recognition_result = OPENCHAOJI_GBT27930_A_RECOGNIZE_TYPE_NOT_RECOGNIZED; // 初始化辨识结果
    context->running_data.a->msg_crm.charger_id = OpenChaoJi_secc_app_get_charger_id(context); // 充电机编号
    OpenChaoJi_secc_app_get_charger_location(context, context->running_data.a->msg_crm.charger_location); // 充电机/充电站所在区域编码
    // CML 从app_start函数中传递参数（建议传最大值）
    context->running_data.a->msg_cml.max_output_voltage = context->running_data.a->app_start_parameter.parameter_max_charging_volt; // 充电机最高充电电压
    context->running_data.a->msg_cml.min_output_voltage = context->running_data.a->app_start_parameter.parameter_min_charging_volt; // 充电机最低充电电压
    context->running_data.a->msg_cml.max_output_current = 4000 - context->running_data.a->app_start_parameter.parameter_max_charging_curr; // 充电机最大充电电流
    context->running_data.a->msg_cml.min_output_current = 4000 - context->running_data.a->app_start_parameter.parameter_min_charging_curr; // 充电机最小充电电流
    // CSD
    context->running_data.a->msg_csd.charger_id = OpenChaoJi_secc_app_get_charger_id(context); // 充电机编号
}
static void OpenChaoJi_gbt27930_a_secc_post_handshake_s0_init(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_handshake_s0_init(struct OpenChaoJi_secc_context * context)
{
    if (!context->running_data.a->reconnect_flag) // 首次通信连接
    {
        LOG_NOTICE("[%d]Handshake S0 communicate start", context->tag);

        // 发送CHM报文
        LOG_INFO("[%d]Handshake S0 send chm", context->tag);
        OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CHM, (uint8_t *)(&context->running_data.a->msg_chm), sizeof(context->running_data.a->msg_chm));

        // 打开TCPchm
        LOG_INFO("[%d]Handshake S0 start timer TCPchm", context->tag);
        OpenChaoJi_os_soft_timer_start(&context->running_data.a->tcp_chm, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCPCHM);

        // 打开TCObhm
        LOG_INFO("[%d]Handshake S0 start timer TCObhm", context->tag);
        OpenChaoJi_os_soft_timer_start(&context->running_data.a->tco_bhm, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCOBHM);

        // 进入S1
        LOG_NOTICE("[%d]Handshake S0 To S1", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_HANDSHAKE_S1_WAIT_BHM;
    }
    else //if (context->running_data.a->reconnect_flag) // 通信重连
    {
        LOG_NOTICE("[%d]Handshake S0 reconnect", context->tag);

        // 发送CRM报文
        LOG_INFO("[%d]Handshake S0 send crm", context->tag);
        OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CRM, (uint8_t *)(&context->running_data.a->msg_crm), sizeof(context->running_data.a->msg_crm));

        // 打开TCPcrm
        LOG_INFO("[%d]Handshake S0 start timer TCPcrm", context->tag);
        OpenChaoJi_os_soft_timer_start(&context->running_data.a->tcp_crm, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCPCRM);

        // 打开TCObrm
        LOG_INFO("[%d]Handshake S0 start timer TCObrm", context->tag);
        OpenChaoJi_os_soft_timer_start(&context->running_data.a->tco_brm, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCOBRM);

        // 进入S3
        LOG_NOTICE("[%d]Handshake S0 To S3", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_HANDSHAKE_S3_WAIT_BRM;
    }
}

static void OpenChaoJi_gbt27930_a_secc_prev_handshake_s1_wait_bhm(struct OpenChaoJi_secc_context * context)
{
    context->running_data.a->msg_bhm_ok = 0;
}
static void OpenChaoJi_gbt27930_a_secc_post_handshake_s1_wait_bhm(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_handshake_s1_wait_bhm(struct OpenChaoJi_secc_context * context)
{
    // TCPchm定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tcp_chm))
    {
        // 发送CHM报文
        LOG_INFO("[%d]Handshake S1 send chm", context->tag);
        OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CHM, (uint8_t *)(&context->running_data.a->msg_chm),sizeof(context->running_data.a->msg_chm));

        // 重置TCPchm
        LOG_INFO("[%d]Handshake S1 reset timer TCPchm", context->tag);
        OpenChaoJi_os_soft_timer_reset(&context->running_data.a->tcp_chm);
    }

    // 接收车辆BHM报文
    if (context->running_data.a->msg_bhm_ok)
    {
        LOG_NOTICE("[%d]Handshake S1 bhm received", context->tag);

        // 关闭TCObhm
        LOG_INFO("[%d]Handshake S1 stop timer TCObhm", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bhm);

        // 启动充电机自检, 放到S2 prev阶段执行

        // 进入S2
        LOG_NOTICE("[%d]Handshake S1 To S2", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_HANDSHAKE_S2_SELFCHECK;
    }

    // TCObhm定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_bhm))
    {
        LOG_NOTICE("[%d]Handshake S1 bhm timeout", context->tag);

        //协议版本V1.0
        context->running_data.a->protocol_version = OPENCHAOJI_GBT27930_A_PROTOCOL_VERSION_TYPE_MAKE(1,0,0);

        // 启动充电机自检, 放到S2 prev阶段执行

        // 进入S2
        LOG_NOTICE("[%d]Handshake S1 To S2", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_HANDSHAKE_S2_SELFCHECK;
    }

    // 未收到, 未超时, 继续等待, 保持S1
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_HANDSHAKE_S1_WAIT_BHM;
}

static void OpenChaoJi_gbt27930_a_secc_prev_handshake_s2_selfcheck(struct OpenChaoJi_secc_context * context)
{
    // 按照APP参数更新
    uint32_t voltage = context->running_data.a->app_start_parameter.parameter_max_charging_volt;
    uint32_t max_voltage = context->running_data.a->app_start_parameter.parameter_max_charging_volt;
    uint32_t min_voltage = context->running_data.a->app_start_parameter.parameter_min_charging_volt;

    context->running_data.a->handshake.seftcheck_ok = 0;
    LOG_NOTICE("[%d]Handshake S2 selfcheck init", context->tag);

    // 确认自检电压
    if (context->running_data.a->msg_bhm_ok) // 接收到BHM报文
    {
        // 校验BHM绝缘监测允许总电压是否正常
        if (min_voltage >= context->running_data.a->msg_bhm.insul_request_voltage)
        {
            LOG_NOTICE("[%d]Handshake S2 selfcheck param error, min_voltage=%d, bhm_voltage=%d", context->tag, min_voltage, context->running_data.a->msg_bhm.insul_request_voltage);
            // 自检参数错误
            context->running_data.a->handshake.seftcheck_start = 0;
        }
        else if (max_voltage >= context->running_data.a->msg_bhm.insul_request_voltage)
        {
            // 参数正常, 按照BHM电压自检
            LOG_NOTICE("[%d]Handshake S2 selfcheck param match, max_voltage=%d, bhm_voltage=%d", context->tag, max_voltage, context->running_data.a->msg_bhm.insul_request_voltage);
            voltage = context->running_data.a->msg_bhm.insul_request_voltage;
            context->running_data.a->handshake.seftcheck_start = 1;
        }
        else
        {
            // 参数正常, 按照充电机最高充电电压自检
            LOG_NOTICE("[%d]Handshake S2 selfcheck param match, max_voltage=%d, bhm_voltage=%d", context->tag, max_voltage, context->running_data.a->msg_bhm.insul_request_voltage);
            context->running_data.a->handshake.seftcheck_start = 1;
        }
    }
    else
    {
        // 未收到BHM, 按照充电机最高充电电压自检
        LOG_NOTICE("[%d]Handshake S2 selfcheck without bhm, max_voltage=%d", context->tag, max_voltage);
        context->running_data.a->handshake.seftcheck_start = 1;
    }

    // 启动自检
    if (context->running_data.a->handshake.seftcheck_start)
    {
        LOG_NOTICE("[%d]Handshake S2 selfcheck start, voltage=%d", context->tag, voltage);
        OpenChaoJi_secc_hal_selfcheck_request_start(context->hal_handle, voltage);
    }
}
static void OpenChaoJi_gbt27930_a_secc_post_handshake_s2_selfcheck(struct OpenChaoJi_secc_context * context)
{
    LOG_NOTICE("[%d]Handshake S2 selfcheck stop", context->tag);
    OpenChaoJi_secc_hal_selfcheck_request_stop(context->hal_handle);
}
static int  OpenChaoJi_gbt27930_a_secc_loop_handshake_s2_selfcheck(struct OpenChaoJi_secc_context * context)
{
    // 自检参数
    if (!context->running_data.a->handshake.seftcheck_start) // 自检参数错误
    {
        LOG_NOTICE("[%d]Handshake S2 selfcheck exit", context->tag);

        // 关闭TCPchm
        LOG_INFO("[%d]Handshake S2 stop timer TCPchm", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_chm);

        // 发送CST报文, 此处只更新故障代码, 在故障处理阶段执行发送
        context->running_data.a->msg_cst.stop_code.bits.fault_suspends = 0x01; // 故障中止
        context->running_data.a->msg_cst.fault_code.bits.self_check_fault = 0x01; // 自检故障

        // 进入故障处理阶段
        LOG_ERR("[%d]Handshake S2 To S5", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_HANDSHAKE_S5_FAULT;
    }

    // TCPchm定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tcp_chm))
    {
        // 发送CHM报文
        LOG_INFO("[%d]Handshake S2 send chm", context->tag);
        OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CHM, (uint8_t *)(&context->running_data.a->msg_chm), sizeof(context->running_data.a->msg_chm));

        // 重置TCPchm
        LOG_INFO("[%d]Handshake S2 reset timer TCPchm", context->tag);
        OpenChaoJi_os_soft_timer_reset(&context->running_data.a->tcp_chm);
    }

    // 获取自检结果 GB/T 18487.1 B.4.7.7
    // 自检成功: 粘连检测、短路检测、绝缘检测完成, 并且检测结果都是成功, 则认为自检成功
    // 自检失败: 粘连检测、短路检测、绝缘检测完成, 并且检测结果中任一项是失败, 则认为自检失败
    struct OpenChaoJi_secc_hal_selfdata selfcheck_result;
    selfcheck_result = OpenChaoJi_secc_hal_selfcheck_get_result(context->hal_handle); // 自检状态 + 自检结果
    if ((selfcheck_result.selfsta_adhesion == SELFSTA_ADHESION_END && selfcheck_result.selfres_adhesion == SELFRES_ADHESION_SUCCESS) && \
        (selfcheck_result.selfsta_short == SELFSTA_SHORT_END && selfcheck_result.selfres_short == SELFRES_SHORT_SUCCESS) && \
        (selfcheck_result.selfsta_imd == SELFSTA_IMD_END && selfcheck_result.selfres_imd == SELFRES_IMD_SUCCESS))
    {
        LOG_NOTICE("[%d]Handshake S2 SeftCheck Succeed", context->tag);
        context->running_data.a->handshake.seftcheck_ok = 1;
    }
    else if ((selfcheck_result.selfsta_adhesion == SELFSTA_ADHESION_END && selfcheck_result.selfres_adhesion == SELFRES_ADHESION_ERROR) || \
        (selfcheck_result.selfsta_short == SELFSTA_SHORT_END && selfcheck_result.selfres_short == SELFRES_SHORT_ERROR) || \
        (selfcheck_result.selfsta_imd == SELFSTA_IMD_END && selfcheck_result.selfres_imd == SELFRES_IMD_ERROR))
    {
        LOG_ERR("[%d]Handshake S2 SeftCheck Failed", context->tag);
        context->running_data.a->handshake.seftcheck_ok = 2;
    }

    if (context->running_data.a->handshake.seftcheck_ok == 1) // 自检成功
    {
        // 关闭TCPchm
        LOG_INFO("[%d]Handshake S2 stop timer TCPchm", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_chm);

        // 发送CRM报文
        LOG_INFO("[%d]Handshake S2 send crm", context->tag);
        OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CRM, (uint8_t *)(&context->running_data.a->msg_crm), sizeof(context->running_data.a->msg_crm));

        // 打开TCPcrm
        LOG_INFO("[%d]Handshake S2 start timer TCPcrm", context->tag);
        OpenChaoJi_os_soft_timer_start(&context->running_data.a->tcp_crm, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCPCRM);

        // 打开TCObrm
        LOG_INFO("[%d]Handshake S2 start timer TCObrm", context->tag);
        OpenChaoJi_os_soft_timer_start(&context->running_data.a->tco_brm, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCOBRM);

        // 进入S3
        LOG_NOTICE("[%d]Handshake S2 To S3", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_HANDSHAKE_S3_WAIT_BRM;
    }
    else if (context->running_data.a->handshake.seftcheck_ok == 2) // 自检失败
    {
        // 关闭TCPchm
        LOG_INFO("[%d]Handshake S2 stop timer TCPchm", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_chm);

        // 发送CST报文, 此处只更新故障代码, 在故障处理阶段执行发送
        context->running_data.a->msg_cst.stop_code.bits.fault_suspends = 0x01; // 故障中止
        context->running_data.a->msg_cst.fault_code.bits.self_check_fault = 0x01; // 自检故障

        // 进入S5
        LOG_ERR("[%d]Handshake S2 To S5", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_HANDSHAKE_S5_FAULT;
    }

    // 自检未完成, 继续等待, 保持S2
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_HANDSHAKE_S2_SELFCHECK;
}

static void OpenChaoJi_gbt27930_a_secc_prev_handshake_s3_wait_brm(struct OpenChaoJi_secc_context * context)
{
    context->running_data.a->msg_brm_ok = 0;
}
static void OpenChaoJi_gbt27930_a_secc_post_handshake_s3_wait_brm(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_handshake_s3_wait_brm(struct OpenChaoJi_secc_context * context)
{
    // TCPcrm定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tcp_crm))
    {
        // 发送CRM报文
        LOG_INFO("[%d]Handshake S3 send crm", context->tag);
        OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CRM, (uint8_t *)(&context->running_data.a->msg_crm), sizeof(context->running_data.a->msg_crm));

        // 重置TCPcrm
        LOG_INFO("[%d]Handshake S3 reset timer TCPcrm", context->tag);
        OpenChaoJi_os_soft_timer_reset(&context->running_data.a->tcp_crm);
    }

    // 接收车辆BRM报文
    if (context->running_data.a->msg_brm_ok)
    {
        LOG_NOTICE("[%d]Handshake S3 brm received", context->tag);

        // 关闭TCObrm
        LOG_INFO("[%d]Handshake S3 stop timer TCObrm", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_brm);

        // CRM报文数据变更为SPN2560=0xAA
        LOG_INFO("[%d]Handshake S3 CRM=0xAA", context->tag);
        context->running_data.a->msg_crm.recognition_result = OPENCHAOJI_GBT27930_A_RECOGNIZE_TYPE_RECOGNIZED;

        // 进入S4
        LOG_NOTICE("[%d]Handshake S3 To S4", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_HANDSHAKE_S4_SUCCEED;
    }

    // TCObrm定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_brm))
    {
        LOG_ERR("[%d]Handshake S3 brm timeout", context->tag);

        // 关闭TCPcrm
        LOG_INFO("[%d]Handshake S3 stop timer TCPcrm", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_crm);

        // 发送CEM报文, 此处只更新错误代码, 进入错误处理阶段后执行发送
        context->running_data.a->msg_cem.tout_code.bits.timeout_brm = 0x01; // BRM超时

        // 进入S6
        LOG_ERR("[%d]Handshake S3 To S6", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_HANDSHAKE_S6_ERROR;
    }

    // 未收到, 未超时, 继续等待, 保持S3
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_HANDSHAKE_S3_WAIT_BRM;
}

static void OpenChaoJi_gbt27930_a_secc_prev_handshake_s4_succeed(struct OpenChaoJi_secc_context * context) {}
static void OpenChaoJi_gbt27930_a_secc_post_handshake_s4_succeed(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_handshake_s4_succeed(struct OpenChaoJi_secc_context * context)
{
    // 保持TCPcrm
    // 进入充电参数配置阶段
    LOG_NOTICE("[%d]Handshake S4 To Config S0", context->tag);
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S0_INIT;
}

static void OpenChaoJi_gbt27930_a_secc_prev_handshake_s5_fault(struct OpenChaoJi_secc_context * context) {}
static void OpenChaoJi_gbt27930_a_secc_post_handshake_s5_fault(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_handshake_s5_fault(struct OpenChaoJi_secc_context * context)
{
    // 进入故障处理阶段
    LOG_ERR("[%d]Handshake S5 To Charge S5", context->tag);
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S5_EV_STOP;
}

static void OpenChaoJi_gbt27930_a_secc_prev_handshake_s6_error(struct OpenChaoJi_secc_context * context) {}
static void OpenChaoJi_gbt27930_a_secc_post_handshake_s6_error(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_handshake_s6_error(struct OpenChaoJi_secc_context * context)
{
    // 进入错误处理阶段
    LOG_ERR("[%d]Handshake S6 To Error S0", context->tag);
    context->running_data.a->stop_ticks = OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_STOP_TIMEOUT;
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_ERROR_S0_INIT;
}

const struct OpenChaoJi_secc_module_status c_sytem_a_secc_status_array_handshake[OPENCHAOJI_GBT27930_A_SECC_STATUS_HANDSHAKE_NUM] = {
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_HANDSHAKE_S0_INIT,
        .name = "Handshake.S0.Init",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_handshake_s0_init,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_handshake_s0_init,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_handshake_s0_init,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_HANDSHAKE_S1_WAIT_BHM,
        .name = "Handshake.S1.Wait_BHM",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_handshake_s1_wait_bhm,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_handshake_s1_wait_bhm,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_handshake_s1_wait_bhm,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_HANDSHAKE_S2_SELFCHECK,
        .name = "Handshake.S2.Selfcheck",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_handshake_s2_selfcheck,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_handshake_s2_selfcheck,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_handshake_s2_selfcheck,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_HANDSHAKE_S3_WAIT_BRM,
        .name = "Handshake.S3.Wait_BRM",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_handshake_s3_wait_brm,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_handshake_s3_wait_brm,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_handshake_s3_wait_brm,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_HANDSHAKE_S4_SUCCEED,
        .name = "Handshake.S4.Succeed",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_handshake_s4_succeed,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_handshake_s4_succeed,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_handshake_s4_succeed,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_HANDSHAKE_S5_FAULT,
        .name = "Handshake.S5.Fault",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_handshake_s5_fault,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_handshake_s5_fault,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_handshake_s5_fault,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_HANDSHAKE_S6_ERROR,
        .name = "Handshake.S6.Error",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_handshake_s6_error,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_handshake_s6_error,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_handshake_s6_error,
    },
};

const struct OpenChaoJi_secc_module c_gbt27930_a_secc_module_handshake =
{
    .module_id = OPENCHAOJI_GBT27930_A_MODULE_HANDSHAKE,
    .name = "Handshake",
    .status_array = c_sytem_a_secc_status_array_handshake,
    .status_array_len = OPENCHAOJI_GBT27930_A_SECC_STATUS_HANDSHAKE_NUM,
};

/* -------------- 参数配置 模块 国网 -------------- */

static void OpenChaoJi_gbt27930_a_secc_prev_config_s0_init(struct OpenChaoJi_secc_context * context)
{
    LOG_NOTICE("[%d]Config Status Start", context->tag);
    LOG_NOTICE("[%d]Config S0 init", context->tag);
    memset(&context->running_data.a->config, 0, sizeof(context->running_data.a->config));
}
static void OpenChaoJi_gbt27930_a_secc_post_config_s0_init(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_config_s0_init(struct OpenChaoJi_secc_context * context)
{
    // 进入S1
    LOG_NOTICE("[%d]Config S0 To S1", context->tag);
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S1_WAIT_BCP;
}

static void OpenChaoJi_gbt27930_a_secc_prev_config_s1_wait_bcp(struct OpenChaoJi_secc_context * context)
{
    context->running_data.a->msg_bcp_ok = 0;
    context->running_data.a->config.bcp_timer_start = 0;
}
static void OpenChaoJi_gbt27930_a_secc_post_config_s1_wait_bcp(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_config_s1_wait_bcp(struct OpenChaoJi_secc_context * context)
{
    // TCPcrm定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tcp_crm))
    {
        // 发送CRM报文
        LOG_INFO("[%d]Config S1 send crm", context->tag);
        OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CRM, (uint8_t *)(&context->running_data.a->msg_crm), sizeof(context->running_data.a->msg_crm));

        // 重置TCPcrm
        LOG_INFO("[%d]Config S1 reset timer TCPcrm", context->tag);
        OpenChaoJi_os_soft_timer_reset(&context->running_data.a->tcp_crm);

        // 首次发送CRM=0xAA时, 打开TCObcp
        if (!context->running_data.a->config.bcp_timer_start)
        {
            context->running_data.a->config.bcp_timer_start = 1;

            // 打开TCObcp
            LOG_INFO("[%d]Config S1 start timer TCObcp", context->tag);
            OpenChaoJi_os_soft_timer_start(&context->running_data.a->tco_bcp, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCOBCP);
        }
    }

    // 接收车辆BCP报文
    if (context->running_data.a->msg_bcp_ok)
    {
        context->running_data.a->msg_bcp_ok = 0;

        LOG_NOTICE("[%d]Config S1 bcp received", context->tag);

        // 关闭TCPcrm
        LOG_INFO("[%d]Config S1 stop timer TCPcrm", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_crm);

        // 关闭TCObcp
        LOG_INFO("[%d]Config S1 stop timer TCObcp", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bcp);

        // 进入S2
        LOG_NOTICE("[%d]Config S1 To S2", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S2_CHECK_PARAM;
    }

    // TCObcp定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_bcp))
    {
        LOG_ERR("[%d]Config S1 bcp timeout", context->tag);

        // 关闭TCPcrm
        LOG_INFO("[%d]Config S1 stop timer TCPcrm", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_crm);

        // 发送CEM报文, 此处只更新错误代码, 进入错误处理阶段后执行发送
        context->running_data.a->msg_cem.tout_code.bits.timeout_bcp = 0x01; // BCP超时

        // 进入S9
        LOG_ERR("[%d]Config S1 To S9", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S9_ERROR;
    }

    // 未收到, 未超时, 继续等待, 保持S1
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S1_WAIT_BCP;
}

static void OpenChaoJi_gbt27930_a_secc_prev_config_s2_check_param(struct OpenChaoJi_secc_context * context) {}
static void OpenChaoJi_gbt27930_a_secc_post_config_s2_check_param(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_config_s2_check_param(struct OpenChaoJi_secc_context * context)
{
    // 获取当前时钟数据
    time_t time = OpenChaoJi_os_get_time();
    struct tm *time_info = localtime(&time);
    context->running_data.a->msg_cts.time[0] = OpenChaoJi_gbt27930_a_secc_hex_to_bcd(time_info->tm_sec);                    // 秒
    context->running_data.a->msg_cts.time[1] = OpenChaoJi_gbt27930_a_secc_hex_to_bcd(time_info->tm_min);                    // 分
    context->running_data.a->msg_cts.time[2] = OpenChaoJi_gbt27930_a_secc_hex_to_bcd(time_info->tm_hour);                   // 时
    context->running_data.a->msg_cts.time[3] = OpenChaoJi_gbt27930_a_secc_hex_to_bcd(time_info->tm_mday);                   // 日
    context->running_data.a->msg_cts.time[4] = OpenChaoJi_gbt27930_a_secc_hex_to_bcd(time_info->tm_mon + 1);                // 月
    context->running_data.a->msg_cts.time[5] = OpenChaoJi_gbt27930_a_secc_hex_to_bcd((time_info->tm_year + 1900) / 100);    // 年-高位
    context->running_data.a->msg_cts.time[6] = OpenChaoJi_gbt27930_a_secc_hex_to_bcd((time_info->tm_year + 1900) % 100);    // 年-低位

    // 发送CTS报文（时钟同步）
    LOG_INFO("[%d]Config S2 send cts", context->tag);
    OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CTS, (uint8_t *)(&context->running_data.a->msg_cts), sizeof(context->running_data.a->msg_cts));

    // 打开TCPcts
    LOG_INFO("[%d]Config S2 start timer TCPcts", context->tag);
    OpenChaoJi_os_soft_timer_start(&context->running_data.a->tcp_cts, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCPCTS);

    // 发送CML报文
    LOG_INFO("[%d]Config S2 send cml", context->tag);
    OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CML, (uint8_t *)(&context->running_data.a->msg_cml), sizeof(context->running_data.a->msg_cml));

    // 打开TCPcml
    LOG_INFO("[%d]Config S2 start timer TCPcml", context->tag);
    OpenChaoJi_os_soft_timer_start(&context->running_data.a->tcp_cml, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCPCML);

    // 车辆参数匹配判断
    if (context->running_data.a->msg_bcp.allow_voltage >= context->running_data.a->msg_cml.min_output_voltage && \
        context->running_data.a->msg_bcp.measured_voltage <= context->running_data.a->msg_cml.max_output_voltage ) // 参数匹配成功
    {
        LOG_NOTICE("[%d]Config S2 bcp param match", context->tag);

        // 打开TCObro
        LOG_INFO("[%d]Config S2 start timer TCObro", context->tag);
        OpenChaoJi_os_soft_timer_start(&context->running_data.a->tco_bro, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCOBRO);

        // 打开TCObroAA
        LOG_INFO("[%d]Config S2 start timer TCObroAA", context->tag);
        OpenChaoJi_os_soft_timer_start(&context->running_data.a->tco_bro_aa, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCOBRO_AA);

        // 进入S3
        LOG_NOTICE("[%d]Config S2 To S3", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S3_WAIT_BRO;
    }
    else // 参数匹配失败
    {
        LOG_NOTICE("[%d]Config S2 bcp param mismatch", context->tag);

        // 发送CML报文
        LOG_INFO("[%d]Config S2 send cml", context->tag);
        OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CML, (uint8_t *)(&context->running_data.a->msg_cml), sizeof(context->running_data.a->msg_cml));

        // 发送CST报文, 此处只更新故障代码, 在故障处理阶段执行发送
        context->running_data.a->msg_cst.stop_code.bits.fault_suspends = 0x01; // 故障中止
        context->running_data.a->msg_cst.error_code.bits.param_mismatch_error = 0x01; // 充电参数不匹配

        // 进入S8
        LOG_ERR("[%d]Config S2 To S8", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S8_FAULT;
    }
}

static void OpenChaoJi_gbt27930_a_secc_prev_config_s3_wait_bro(struct OpenChaoJi_secc_context * context)
{
    context->running_data.a->msg_bro_ok = 0;
}
static void OpenChaoJi_gbt27930_a_secc_post_config_s3_wait_bro(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_config_s3_wait_bro(struct OpenChaoJi_secc_context * context)
{
    // TCPcts定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tcp_cts))
    {
        // 获取当前时钟数据
        time_t time = OpenChaoJi_os_get_time();
        struct tm *time_info = localtime(&time);
        context->running_data.a->msg_cts.time[0] = OpenChaoJi_gbt27930_a_secc_hex_to_bcd(time_info->tm_sec);                    // 秒
        context->running_data.a->msg_cts.time[1] = OpenChaoJi_gbt27930_a_secc_hex_to_bcd(time_info->tm_min);                    // 分
        context->running_data.a->msg_cts.time[2] = OpenChaoJi_gbt27930_a_secc_hex_to_bcd(time_info->tm_hour);                   // 时
        context->running_data.a->msg_cts.time[3] = OpenChaoJi_gbt27930_a_secc_hex_to_bcd(time_info->tm_mday);                   // 日
        context->running_data.a->msg_cts.time[4] = OpenChaoJi_gbt27930_a_secc_hex_to_bcd(time_info->tm_mon + 1);                // 月
        context->running_data.a->msg_cts.time[5] = OpenChaoJi_gbt27930_a_secc_hex_to_bcd((time_info->tm_year + 1900) / 100);    // 年-高位
        context->running_data.a->msg_cts.time[6] = OpenChaoJi_gbt27930_a_secc_hex_to_bcd((time_info->tm_year + 1900) % 100);    // 年-低位

        // 发送CTS报文（时钟同步）
        LOG_INFO("[%d]Config S3 send cts", context->tag);
        OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CTS, (uint8_t *)(&context->running_data.a->msg_cts), sizeof(context->running_data.a->msg_cts));

        // 重置TCPcts
        LOG_INFO("[%d]Config S3 reset timer TCPcts", context->tag);
        OpenChaoJi_os_soft_timer_reset(&context->running_data.a->tcp_cts);
    }

    // TCPcml定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tcp_cml))
    {
        // 发送CML报文
        LOG_INFO("[%d]Config S3 send cml", context->tag);
        OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CML, (uint8_t *)(&context->running_data.a->msg_cml), sizeof(context->running_data.a->msg_cml));

        // 重置TCPcml
        LOG_INFO("[%d]Config S3 reset timer TCPcml", context->tag);
        OpenChaoJi_os_soft_timer_reset(&context->running_data.a->tcp_cml);
    }

    // 接收车辆BCP报文
    if (context->running_data.a->msg_bcp_ok)
    {
        context->running_data.a->msg_bcp_ok = 0;
        // 同步更新配置参数
        LOG_INFO("[%d]Config S3 bcp received", context->tag);
    }

    // 接收车辆BRO报文
    if (context->running_data.a->msg_bro_ok)
    {
        LOG_INFO("[%d]Config S3 bro received", context->tag);

        // 重置TCObro
        LOG_INFO("[%d]Config S3 reset timer TCObro", context->tag);
        OpenChaoJi_os_soft_timer_reset(&context->running_data.a->tco_bro);

        // BRO就绪状态
        if (context->running_data.a->msg_bro.bms_ready == OPENCHAOJI_GBT27930_A_READY_TYPE_READY)
        {
            LOG_NOTICE("[%d]Config S3 bro is ready", context->tag);
        }
        else
        {
            LOG_NOTICE("[%d]Config S3 bro is not ready", context->tag);
        }

        // 进入S4
        LOG_NOTICE("[%d]Config S3 To S4", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S4_RECHECK_PARAM;
    }

    // TCObro定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_bro))
    {
        LOG_ERR("[%d]Config S3 bro timeout", context->tag);

        // 关闭TCPcml
        LOG_INFO("[%d]Config S3 stop timer TCPcml", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_cml);

        // 关闭TCPcts
        LOG_INFO("[%d]Config S3 stop timer TCPcts", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_cts);

        // 关闭TCObroAA
        LOG_INFO("[%d]Config S3 stop timer TCObroAA", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bro_aa);

        // 发送CEM报文, 此处只更新错误代码, 进入错误处理阶段后执行发送
        context->running_data.a->msg_cem.tout_code.bits.timeout_bro = 0x01; // BRO超时

        // 进入S9
        LOG_ERR("[%d]Config S3 To S9", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S9_ERROR;
    }

    // TCObroAA定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_bro_aa))
    {
        LOG_ERR("[%d]Config S3 bro_AA timeout", context->tag);

        // 关闭TCPcml
        LOG_INFO("[%d]Config S3 stop timer TCPcml", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_cml);

        // 关闭TCPcts
        LOG_INFO("[%d]Config S3 stop timer TCPcts", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_cts);

        // 关闭TCObro
        LOG_INFO("[%d]Config S3 stop timer TCObro", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bro);

        // 发送CEM报文, 此处只更新错误代码, 进入错误处理阶段后执行发送
        context->running_data.a->msg_cem.tout_code.bits.timeout_bro = 0x01; // BRO超时/BRO_AA超时错误码相同

        // 进入S9
        LOG_ERR("[%d]Config S3 To S9", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S9_ERROR;
    }

    // 未收到, 未超时, 继续等待, 保持S3
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S3_WAIT_BRO;
}

static void OpenChaoJi_gbt27930_a_secc_prev_config_s4_recheck_param(struct OpenChaoJi_secc_context * context) {}
static void OpenChaoJi_gbt27930_a_secc_post_config_s4_recheck_param(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_config_s4_recheck_param(struct OpenChaoJi_secc_context * context)
{
    // 车辆参数匹配结果(二次确认)
    if (context->running_data.a->msg_bcp.allow_voltage >= context->running_data.a->msg_cml.min_output_voltage && \
        context->running_data.a->msg_bcp.measured_voltage <= context->running_data.a->msg_cml.max_output_voltage ) // 参数匹配成功
    {
        LOG_NOTICE("[%d]Config S4 bcp param match", context->tag);

        if (context->running_data.a->msg_bro.bms_ready == OPENCHAOJI_GBT27930_A_READY_TYPE_READY) // 车辆已就绪
        {
            // 进入S5
            LOG_NOTICE("[%d]Config S4 To S5", context->tag);
            return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S5_EV_READY;
        }
        else if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_bro_aa)) // TCObroAA定时器到
        {
            LOG_ERR("[%d]Config S4 bro_AA timeout", context->tag);

            // 关闭TCPcml
            LOG_INFO("[%d]Config S4 stop timer TCPcml", context->tag);
            OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_cml);

            // 关闭TCPcts
            LOG_INFO("[%d]Config S4 stop timer TCPcts", context->tag);
            OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_cts);

            // 关闭TCObro
            LOG_INFO("[%d]Config S4 stop timer TCObro", context->tag);
            OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bro);

            // 发送CEM报文, 此处只更新错误代码, 进入错误处理阶段后执行发送
            context->running_data.a->msg_cem.tout_code.bits.timeout_bro = 0x01; // BRO超时/BRO_AA超时错误码相同

            // 进入S9
            LOG_ERR("[%d]Config S4 To S9", context->tag);
            return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S9_ERROR;
        }
        else // 车辆未就绪
        {
            // 进入S3
            LOG_NOTICE("[%d]Config S4 To S3", context->tag);
            return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S3_WAIT_BRO;
        }
    }
    else // 参数匹配失败
    {
        LOG_NOTICE("[%d]Config S4 bcp param mismatch", context->tag);

        // 关闭TCObro
        LOG_INFO("[%d]Config S4 stop timer TCObro", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bro);

        // 关闭TCObroAA
        LOG_INFO("[%d]Config S4 stop timer TCObroAA", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bro_aa);

        // 发送CML报文
        LOG_INFO("[%d]Config S4 send cml", context->tag);
        OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CML, (uint8_t *)(&context->running_data.a->msg_cml), sizeof(context->running_data.a->msg_cml));

        // 发送CST报文, 此处只更新故障代码, 在故障处理阶段执行发送
        context->running_data.a->msg_cst.stop_code.bits.fault_suspends = 0x01; // 故障中止
        context->running_data.a->msg_cst.error_code.bits.param_mismatch_error = 0x01; // 充电参数不匹配

        // 进入S8
        LOG_ERR("[%d]Config S4 To S8", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S8_FAULT;
    }
}

static void OpenChaoJi_gbt27930_a_secc_prev_config_s5_ev_ready(struct OpenChaoJi_secc_context * context) {}
static void OpenChaoJi_gbt27930_a_secc_post_config_s5_ev_ready(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_config_s5_ev_ready(struct OpenChaoJi_secc_context * context)
{
    LOG_NOTICE("[%d]Config S5 EVCC is Ready", context->tag);

    // 关闭TCPcts
    LOG_INFO("[%d]Config S5 stop timer TCPcts", context->tag);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_cts);

    // 关闭TCPcml
    LOG_INFO("[%d]Config S5 stop timer TCPcml", context->tag);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_cml);

    // 准备CRO报文内容, SPN2830=0x00
    context->running_data.a->msg_cro.charger_ready_for_charging = OPENCHAOJI_GBT27930_A_READY_TYPE_NOT_READY; // 初始未就绪状态

    // 发送CRO报文
    LOG_INFO("[%d]Config S5 send cro_00", context->tag);
    OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CRO, (uint8_t *)(&context->running_data.a->msg_cro), sizeof(context->running_data.a->msg_cro));

    // 打开TCPcro
    LOG_INFO("[%d]Config S5 start timer TCPcro", context->tag);
    OpenChaoJi_os_soft_timer_start(&context->running_data.a->tcp_cro, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCPCRO);

    // 进入S6
    LOG_NOTICE("[%d]Config S5 To S6", context->tag);
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S6_PRE_CHARGE;
}

static void OpenChaoJi_gbt27930_a_secc_prev_config_s6_pre_charge(struct OpenChaoJi_secc_context * context)
{
    context->running_data.a->msg_bro_ok = 0;
}
static void OpenChaoJi_gbt27930_a_secc_post_config_s6_pre_charge(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_config_s6_pre_charge(struct OpenChaoJi_secc_context * context)
{
    // TCPcro定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tcp_cro))
    {
        // 发送CRO报文
        LOG_INFO("[%d]Config S6 send cro_00", context->tag);
        OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CRO, (uint8_t *)(&context->running_data.a->msg_cro), sizeof(context->running_data.a->msg_cro));

        // 重置TCPcro
        LOG_INFO("[%d]Config S6 reset timer TCPcro", context->tag);
        OpenChaoJi_os_soft_timer_reset(&context->running_data.a->tcp_cro);
    }

    // TCObro定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_bro))
    {
        LOG_ERR("[%d]Config S6 bro timeout", context->tag);

        // 关闭TCPcro
        LOG_INFO("[%d]Config S6 stop timer TCPcro", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_cro);

        // 关闭TCObro
        LOG_INFO("[%d]Config S6 stop timer TCObro", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bro);

        // 发送CEM报文, 此处只更新错误代码, 进入错误处理阶段后执行发送
        context->running_data.a->msg_cem.tout_code.bits.timeout_bro = 0x01; // BRO超时

        // 进入S9
        LOG_ERR("[%d]Config S6 To S9", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S9_ERROR;
    }

    // 接收车辆BRO报文
    if (context->running_data.a->msg_bro_ok)
    {
        context->running_data.a->msg_bro_ok = 0;
        LOG_INFO("[%d]Config S6 rcvd bro=0x%02X", context->tag, context->running_data.a->msg_bro.bms_ready);

        if (context->running_data.a->msg_bro.bms_ready != OPENCHAOJI_GBT27930_A_READY_TYPE_READY)
        {
            // SPN2829!=0xAA
            LOG_ERR("[%d]Config S6 EVCC bro ready staus is terminated", context->tag);
        }
    }

    // 车辆就绪状态
    if (context->running_data.a->msg_bro.bms_ready == OPENCHAOJI_GBT27930_A_READY_TYPE_READY) // 车辆就绪
    {
        // 重置TCObro
        LOG_INFO("[%d]Config S6 reset timer TCObro", context->tag);
        OpenChaoJi_os_soft_timer_reset(&context->running_data.a->tco_bro);
    }
    else
    {
        // 关闭TCPcro
        LOG_INFO("[%d]Config S6 stop timer TCPcro", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_cro);

        // 关闭TCObro
        LOG_INFO("[%d]Config S6 stop timer TCObro", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bro);

        // 发送CST报文, 此处只更新故障代码, 在故障处理阶段执行发送
        context->running_data.a->msg_cst.stop_code.bits.fault_suspends = 0x01; // 故障中止
        context->running_data.a->msg_cst.fault_code.bits.precharging_fault = 0x01; // 预充故障

        // 进入S8
        LOG_ERR("[%d]Config S6 To S8", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S8_FAULT;
    }

    // 判断预充是否完成
    if (context->running_data.a->precharge_status == OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_FINISHED) // 预充完成
    {
        LOG_NOTICE("[%d]Config S6 SECC is Ready, PreCharge Finished", context->tag);

        // 关闭TCObro
        LOG_INFO("[%d]Config S6 stop timer TCObro", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bro);

        // CRO报文数据变更为SPN2830=0xAA
        context->running_data.a->msg_cro.charger_ready_for_charging = OPENCHAOJI_GBT27930_A_READY_TYPE_READY;

        // 进入S7
        LOG_NOTICE("[%d]Config S6 To S7", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S7_SUCCEED;
    }
    else if (context->running_data.a->precharge_status == OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_FINISHED) // 预充故障
    {
        LOG_ERR("[%d]Config S6 PreCharge Failed", context->tag);

        // 关闭TCPcro
        LOG_INFO("[%d]Config S6 stop timer TCPcro", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_cro);

        // 关闭TCObro
        LOG_INFO("[%d]Config S6 stop timer TCObro", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bro);

        // 发送CST报文, 此处只更新故障代码, 在故障处理阶段执行发送
        context->running_data.a->msg_cst.stop_code.bits.fault_suspends = 0x01; // 故障中止
        context->running_data.a->msg_cst.fault_code.bits.precharging_fault = 0x01; // 预充故障

        // 进入S8
        LOG_ERR("[%d]Config S6 To S8", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S8_FAULT;
    }

    // 未超时, 继续等待, 保持S6
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S6_PRE_CHARGE;
}

static void OpenChaoJi_gbt27930_a_secc_prev_config_s7_succeed(struct OpenChaoJi_secc_context * context) {}
static void OpenChaoJi_gbt27930_a_secc_post_config_s7_succeed(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_config_s7_succeed(struct OpenChaoJi_secc_context * context)
{
    // 进入充电阶段
    LOG_NOTICE("[%d]Config S7 To Charge S0", context->tag);
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S0_INIT;
}

static void OpenChaoJi_gbt27930_a_secc_prev_config_s8_fault(struct OpenChaoJi_secc_context * context) {}
static void OpenChaoJi_gbt27930_a_secc_post_config_s8_fault(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_config_s8_fault(struct OpenChaoJi_secc_context * context)
{
    // 进入故障处理阶段
    LOG_ERR("[%d]Config S8 To Charge S5", context->tag);
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S5_EV_STOP;
}

static void OpenChaoJi_gbt27930_a_secc_prev_config_s9_error(struct OpenChaoJi_secc_context * context) {}
static void OpenChaoJi_gbt27930_a_secc_post_config_s9_error(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_config_s9_error(struct OpenChaoJi_secc_context * context)
{
    // 进入错误处理阶段
    LOG_ERR("[%d]Config S9 To Error S0", context->tag);
    context->running_data.a->stop_ticks = OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_STOP_TIMEOUT;
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_ERROR_S0_INIT;
}

const struct OpenChaoJi_secc_module_status c_sytem_a_secc_status_array_config[OPENCHAOJI_GBT27930_A_SECC_STATUS_CONFIG_NUM] = {
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S0_INIT,
        .name = "Config.S0.Init",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_config_s0_init,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_config_s0_init,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_config_s0_init,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S1_WAIT_BCP,
        .name = "Config.S1.Wait_BCP",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_config_s1_wait_bcp,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_config_s1_wait_bcp,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_config_s1_wait_bcp,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S2_CHECK_PARAM,
        .name = "Config.S2.Check_Param",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_config_s2_check_param,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_config_s2_check_param,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_config_s2_check_param,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S3_WAIT_BRO,
        .name = "Config.S3.Wait_BRO",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_config_s3_wait_bro,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_config_s3_wait_bro,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_config_s3_wait_bro,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S4_RECHECK_PARAM,
        .name = "Config.S4.ReCheck_Param",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_config_s4_recheck_param,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_config_s4_recheck_param,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_config_s4_recheck_param,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S5_EV_READY,
        .name = "Config.S5.EVCC_Ready",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_config_s5_ev_ready,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_config_s5_ev_ready,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_config_s5_ev_ready,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S6_PRE_CHARGE,
        .name = "Config.S6.PreCharge",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_config_s6_pre_charge,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_config_s6_pre_charge,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_config_s6_pre_charge,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S7_SUCCEED,
        .name = "Config.S7.Succeed",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_config_s7_succeed,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_config_s7_succeed,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_config_s7_succeed,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S8_FAULT,
        .name = "Config.S8.Fault",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_config_s8_fault,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_config_s8_fault,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_config_s8_fault,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S9_ERROR,
        .name = "Config.S9.Error",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_config_s9_error,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_config_s9_error,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_config_s9_error,
    },
};

const struct OpenChaoJi_secc_module c_gbt27930_a_secc_module_config =
{
    .module_id = OPENCHAOJI_GBT27930_A_MODULE_CONFIG,
    .name = "Config",
    .status_array = c_sytem_a_secc_status_array_config,
    .status_array_len = OPENCHAOJI_GBT27930_A_SECC_STATUS_CONFIG_NUM,
};




/* --------------  充电 模块 银河龙芯 -------------- */

static void OpenChaoJi_gbt27930_a_secc_prev_charge_s0_init(struct OpenChaoJi_secc_context * context)
{
    LOG_NOTICE("[%d]Charge Status Start", context->tag);
    LOG_NOTICE("[%d]Charge S0 init", context->tag);
    memset(&context->running_data.a->charge, 0, sizeof(context->running_data.a->charge));
    context->running_data.a->precharge_status = OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_INIT;
}
static void OpenChaoJi_gbt27930_a_secc_post_charge_s0_init(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_charge_s0_init(struct OpenChaoJi_secc_context * context)
{
    // 进入S1
    LOG_NOTICE("[%d]Charge S0 To S1", context->tag);
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S1_WAIT_BCL;
}

static void OpenChaoJi_gbt27930_a_secc_prev_charge_s1_wait_bcl(struct OpenChaoJi_secc_context * context)
{
    context->running_data.a->msg_bcl_ok = 0;
}
static void OpenChaoJi_gbt27930_a_secc_post_charge_s1_wait_bcl(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_charge_s1_wait_bcl(struct OpenChaoJi_secc_context * context)
{
    // TCPcro定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tcp_cro))
    {
        // 发送CRO报文
        LOG_INFO("[%d]Charge S1 send cro_AA", context->tag);
        OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CRO, (uint8_t *)(&context->running_data.a->msg_cro), sizeof(context->running_data.a->msg_cro));

        // 重置TCPcro
        LOG_INFO("[%d]Charge S1 reset timer TCPcro", context->tag);
        OpenChaoJi_os_soft_timer_reset(&context->running_data.a->tcp_cro);

        // 首次发送SPN2830=0xAA的CRO报文时, 打开TCObcl
        if (!context->running_data.a->charge.bcl_timer_start)
        {
            context->running_data.a->charge.bcl_timer_start = 1;

            // 打开TCObcl
            LOG_INFO("[%d]Charge S1 start timer TCObcl", context->tag);
            OpenChaoJi_os_soft_timer_start(&context->running_data.a->tco_bcl, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCOBCL);

            // 打开TCObcs
            LOG_INFO("[%d]Charge S1 start timer TCObcs", context->tag);
            OpenChaoJi_os_soft_timer_start(&context->running_data.a->tco_bcs, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCOBCS);
        }
    }

    // 接收车辆BCL报文
    if (context->running_data.a->msg_bcl_ok)
    {
        context->running_data.a->msg_bcl_ok = 0;

        LOG_NOTICE("[%d]Charge S1 bcl received", context->tag);

        // 重置TCObcl
        LOG_INFO("[%d]Charge S1 reset timer TCObcl", context->tag);
        OpenChaoJi_os_soft_timer_reset(&context->running_data.a->tco_bcl);

        // 关闭TCPcro
        LOG_INFO("[%d]Charge S1 stop timer TCPcro", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_cro);

        // 更新CCS报文内容
        context->running_data.a->msg_ccs.output_voltage_value = OpenChaoJi_secc_hal_power_module_get_voltage(context->hal_handle);
        context->running_data.a->msg_ccs.output_current_value = 4000 - OpenChaoJi_secc_hal_power_module_get_current(context->hal_handle);
        context->running_data.a->msg_ccs.cumulative_charging_time = OpenChaoJi_secc_app_get_charging_time(context);
        context->running_data.a->msg_ccs.state.bits.charging_permissible = OpenChaoJi_secc_app_get_charger_enable(context);

        // 发送CCS报文
        LOG_INFO("[%d]Charge S1 send ccs", context->tag);
        OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CCS, (uint8_t *)(&context->running_data.a->msg_ccs), sizeof(context->running_data.a->msg_ccs));

        // 打开TCPccs
        LOG_INFO("[%d]Charge S1 start timer TCPccs", context->tag);
        OpenChaoJi_os_soft_timer_start(&context->running_data.a->tcp_ccs, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCPCCS);

        // 进入S2
        LOG_NOTICE("[%d]Charge S1 To S2", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S2_ENERGY_TRANS;
    }

    // TCObcl定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_bcl))
    {
        LOG_ERR("[%d]Charge S1 bcl timeout", context->tag);

        // 关闭TCPcro
        LOG_INFO("[%d]Charge S1 stop timer TCPcro", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_cro);

        // 发送CEM报文, 此处只更新错误代码, 进入错误处理阶段后执行发送
        context->running_data.a->msg_cem.tout_code.bits.timeout_bcl = 0x01; // BCL超时

        // 进入S7
        LOG_ERR("[%d]Charge S1 To S7", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S7_ERROR;
    }

    // 未收到, 未超时, 继续等待, 保持S1
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S1_WAIT_BCL;
}

static void OpenChaoJi_gbt27930_a_secc_prev_charge_s2_energy_trans(struct OpenChaoJi_secc_context * context)
{
    context->running_data.a->msg_bcs_ok = 0;
    context->running_data.a->msg_bsm_ok = 0;
}
static void OpenChaoJi_gbt27930_a_secc_post_charge_s2_energy_trans(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_charge_s2_energy_trans(struct OpenChaoJi_secc_context * context)
{
    // TCPccs定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tcp_ccs))
    {
        // 更新CCS报文内容
        context->running_data.a->msg_ccs.output_voltage_value = OpenChaoJi_secc_hal_power_module_get_voltage(context->hal_handle);
        context->running_data.a->msg_ccs.output_current_value = 4000 - OpenChaoJi_secc_hal_power_module_get_current(context->hal_handle);
        context->running_data.a->msg_ccs.cumulative_charging_time = OpenChaoJi_secc_app_get_charging_time(context);
        context->running_data.a->msg_ccs.state.bits.charging_permissible = OpenChaoJi_secc_app_get_charger_enable(context);

        // 发送CCS报文
        LOG_INFO("[%d]Charge S2 send ccs", context->tag);
        OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CCS, (uint8_t *)(&context->running_data.a->msg_ccs), sizeof(context->running_data.a->msg_ccs));

        // 重置TCPccs
        LOG_INFO("[%d]Charge S2 reset timer TCPccs", context->tag);
        OpenChaoJi_os_soft_timer_reset(&context->running_data.a->tcp_ccs);
    }

    // 接收车辆BCL报文
    if (context->running_data.a->msg_bcl_ok)
    {
        context->running_data.a->msg_bcl_ok = 0;
        LOG_INFO("[%d]Charge S2 bcl received, vol=%d, cur=%d, mode=%d", context->tag, context->running_data.a->msg_bcl.target_voltage, 4000 - context->running_data.a->msg_bcl.target_current, context->running_data.a->msg_bcl.charge_mode);

        // 重置TCObcl
        LOG_INFO("[%d]Charge S2 reset timer TCObcl", context->tag);
        OpenChaoJi_os_soft_timer_reset(&context->running_data.a->tco_bcl);

        // 更新充电机输出控制参数

        // GB/T 27930 11.3.1 当BCL报文中的充电电压需求小于充电机的最小充电电压时, 充电机应发送CST报文停止充电
        if (context->running_data.a->msg_bcl.target_voltage < context->running_data.a->msg_cml.min_output_voltage)
        {
            LOG_NOTICE("[%d]Charge S2 bcl param mismatch, min_vol=%d", context->tag, context->running_data.a->msg_cml.min_output_voltage);

            // 发送CST报文, 此处只更新故障代码
            context->running_data.a->msg_cst.stop_code.bits.fault_suspends = 0x01; // 故障中止
            context->running_data.a->msg_cst.error_code.bits.param_mismatch_error = 0x01; // 充电参数不匹配

            // 进入S5
            LOG_ERR("[%d]Charge S2 To S5", context->tag);
            return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S5_EV_STOP;
        }
        else // 按需求输出
        {
            // 获取BCL需求
            context->running_data.a->charge.requirement_parameter.voltage = context->running_data.a->msg_bcl.target_voltage;
            context->running_data.a->charge.requirement_parameter.current = 4000 - context->running_data.a->msg_bcl.target_current;
            context->running_data.a->charge.requirement_parameter.charge_mode = context->running_data.a->msg_bcl.charge_mode;

            // LOG_NOTICE("[%d]Charge S2 Recv Vehicle Charge Requirement", context->tag);
            // 根据车辆需求要求App计算出实际需要下发模块的电压电流值
            OpenChaoJi_secc_app_get_power_output(context
                , &context->running_data.a->charge.requirement_parameter
                , &context->running_data.a->charge.volt_power_module
                , &context->running_data.a->charge.curr_power_module);

            LOG_INFO("[%d]Charge S2 app output param, vol=%d, cur=%d", context->tag, context->running_data.a->charge.volt_power_module, context->running_data.a->charge.curr_power_module);
            // 调节输出
            OpenChaoJi_secc_hal_power_module_request_start(context->hal_handle
                , context->running_data.a->charge.volt_power_module
                , context->running_data.a->charge.curr_power_module);
        }
    }

    // TCObcl定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_bcl))
    {
        LOG_ERR("[%d]Charge S2 bcl timeout", context->tag);

        // 发送CEM报文, 此处只更新错误代码, 进入错误处理阶段后执行发送
        context->running_data.a->msg_cem.tout_code.bits.timeout_bcl = 0x01; // BCL超时

        // 进入S7
        LOG_ERR("[%d]Charge S2 To S7", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S7_ERROR;
    }

    // 接收车辆BCS报文
    if (context->running_data.a->msg_bcs_ok)
    {
        context->running_data.a->msg_bcs_ok = 0;
        LOG_INFO("[%d]Charge S2 bcs received", context->tag);

        // 重置TCObcs
        LOG_INFO("[%d]Charge S2 reset timer TCObcs", context->tag);
        OpenChaoJi_os_soft_timer_reset(&context->running_data.a->tco_bcs);
    }

    // TCObcs定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_bcs))
    {
        LOG_ERR("[%d]Charge S2 bcs timeout", context->tag);

        // 发送CEM报文, 此处只更新错误代码, 进入错误处理阶段后执行发送
        context->running_data.a->msg_cem.tout_code.bits.timeout_bcs = 0x01; // BCS超时

        // 进入S7
        LOG_ERR("[%d]Charge S2 To S7", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S7_ERROR;
    }

    // 接收车辆BSM报文
    if (context->running_data.a->msg_bsm_ok)
    {
        context->running_data.a->msg_bsm_ok = 0;
        LOG_INFO("[%d]Charge S2 bsm received", context->tag);

        // 首次接收到BSM报文时, 打开TCObsm
        if (!context->running_data.a->charge.bsm_rcvd_flag)
        {
            context->running_data.a->charge.bsm_rcvd_flag = 1;

            // 打开TCObsm
            LOG_INFO("[%d]Charge S2 start timer TCObsm", context->tag);
            OpenChaoJi_os_soft_timer_start(&context->running_data.a->tco_bsm, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCOBSM);
        }
        else
        {
            // 重置TCObsm
            LOG_INFO("[%d]Charge S2 reset timer TCObsm", context->tag);
            OpenChaoJi_os_soft_timer_reset(&context->running_data.a->tco_bsm);
        }
    }

    // TCObsm定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_bsm))
    {
        LOG_ERR("[%d]Charge S2 bsm timeout", context->tag);

        // 发送CEM报文, 此处只更新错误代码, 进入错误处理阶段后执行发送
        context->running_data.a->msg_cem.tout_code.bits.timeout_bsm = 0x01; // BSM超时

        // 进入S7
        LOG_ERR("[%d]Charge S2 To S7", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S7_ERROR;
    }

    // 车辆暂停充电 (BSM报文)
    if (context->running_data.a->charge.bsm_rcvd_flag && \
        context->running_data.a->msg_bsm.batt_state.bits.charge_enable == OPENCHAOJI_GBT27930_A_PAUSE_STATUS_PAUSE)
    {
        LOG_NOTICE("[%d]Charge S2 EVCC Start Suspend", context->tag);

        // 打开TCObsup
        LOG_INFO("[%d]Charge S2 start timer TCObsup", context->tag);
        OpenChaoJi_os_soft_timer_start(&context->running_data.a->tco_bsup, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCOBSUP);

        // 进入S4
        LOG_NOTICE("[%d]Charge S2 To S4", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S4_EV_SUSPEND;
    }

    // 充电机暂停充电
    if (OpenChaoJi_secc_app_get_charger_enable(context) == OPENCHAOJI_GBT27930_A_PAUSE_STATUS_PAUSE)
    {
        // CCS报文数据变更为SPN3929=0x00 (状态数据, 实时刷新, 此处无需处理)

        LOG_NOTICE("[%d]Charge S2 SECC Start Suspend", context->tag);

        // 进入S3
        LOG_NOTICE("[%d]Charge S2 To S3", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S3_SE_SUSPEND;
    }

    // 继续等待, 保持S2
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S2_ENERGY_TRANS;
}

static void OpenChaoJi_gbt27930_a_secc_prev_charge_s3_secc_suspend(struct OpenChaoJi_secc_context * context) {}
static void OpenChaoJi_gbt27930_a_secc_post_charge_s3_secc_suspend(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_charge_s3_secc_suspend(struct OpenChaoJi_secc_context * context)
{
    LOG_DEBUG("[%d]Charge S3 secc suspend", context->tag);

    // TCPccs定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tcp_ccs))
    {
        // 更新CCS报文内容
        context->running_data.a->msg_ccs.output_voltage_value = OpenChaoJi_secc_hal_power_module_get_voltage(context->hal_handle);
        context->running_data.a->msg_ccs.output_current_value = 4000 - OpenChaoJi_secc_hal_power_module_get_current(context->hal_handle);
        context->running_data.a->msg_ccs.cumulative_charging_time = OpenChaoJi_secc_app_get_charging_time(context);
        context->running_data.a->msg_ccs.state.bits.charging_permissible = OpenChaoJi_secc_app_get_charger_enable(context);

        // 发送CCS报文
        LOG_INFO("[%d]Charge S3 send ccs", context->tag);
        OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CCS, (uint8_t *)(&context->running_data.a->msg_ccs), sizeof(context->running_data.a->msg_ccs));

        // 重置TCPccs
        LOG_INFO("[%d]Charge S3 reset timer TCPccs", context->tag);
        OpenChaoJi_os_soft_timer_reset(&context->running_data.a->tcp_ccs);
    }

    // 接收车辆BCL报文
    if (context->running_data.a->msg_bcl_ok)
    {
        context->running_data.a->msg_bcl_ok = 0;

        LOG_INFO("[%d]Charge S3 bcl received", context->tag);

        // 重置TCObcl
        LOG_INFO("[%d]Charge S3 reset timer TCObcl", context->tag);
        OpenChaoJi_os_soft_timer_reset(&context->running_data.a->tco_bcl);
    }

    // TCObcl定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_bcl))
    {
        LOG_ERR("[%d]Charge S3 bcl timeout", context->tag);

        // 发送CEM报文, 此处只更新错误代码, 进入错误处理阶段后执行发送
        context->running_data.a->msg_cem.tout_code.bits.timeout_bcl = 0x01; // BCL超时

        // 进入S7
        LOG_ERR("[%d]Charge S3 To S7", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S7_ERROR;
    }

    // 接收车辆BCS报文
    if (context->running_data.a->msg_bcs_ok)
    {
        context->running_data.a->msg_bcs_ok = 0;

        LOG_INFO("[%d]Charge S3 bcs received", context->tag);

        // 重置TCObcs
        LOG_INFO("[%d]Charge S3 reset timer TCObcs", context->tag);
        OpenChaoJi_os_soft_timer_reset(&context->running_data.a->tco_bcs);
    }

    // TCObcs定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_bcs))
    {
        LOG_ERR("[%d]Charge S3 bcs timeout", context->tag);

        // 发送CEM报文, 此处只更新错误代码, 进入错误处理阶段后执行发送
        context->running_data.a->msg_cem.tout_code.bits.timeout_bcs = 0x01; // BCS超时

        // 进入S7
        LOG_ERR("[%d]Charge S3 To S7", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S7_ERROR;
    }

    // 接收车辆BSM报文
    if (context->running_data.a->msg_bsm_ok)
    {
        context->running_data.a->msg_bsm_ok = 0;

        // 首次接收到BSM报文时, 打开TCObsm
        if (!context->running_data.a->charge.bsm_rcvd_flag)
        {
            context->running_data.a->charge.bsm_rcvd_flag = 1;

            LOG_INFO("[%d]Charge S3 bsm received", context->tag);

            // 打开TCObsm
            LOG_INFO("[%d]Charge S3 start timer TCObsm", context->tag);
            OpenChaoJi_os_soft_timer_start(&context->running_data.a->tco_bsm, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCOBSM);
        }
        else
        {
            // 重置TCObsm
            LOG_INFO("[%d]Charge S3 stop timer TCObsm", context->tag);
            OpenChaoJi_os_soft_timer_reset(&context->running_data.a->tco_bsm);
        }
    }

    // TCObsm定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_bsm))
    {
        LOG_ERR("[%d]Charge S3 bsm timeout", context->tag);

        // 发送CEM报文, 此处只更新错误代码, 进入错误处理阶段后执行发送
        context->running_data.a->msg_cem.tout_code.bits.timeout_bsm = 0x01; // BSM超时

        // 进入S7
        LOG_ERR("[%d]Charge S3 To S7", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S7_ERROR;
    }

    // 车辆暂停充电 (BSM报文)
    if (context->running_data.a->charge.bsm_rcvd_flag && \
        context->running_data.a->msg_bsm.batt_state.bits.charge_enable == OPENCHAOJI_GBT27930_A_PAUSE_STATUS_PAUSE)
    {
        LOG_NOTICE("[%d]Charger S3 EVCC Start Suspend", context->tag);

        // 打开TCObsup
        LOG_INFO("[%d]Charge S3 start timer TCObsup", context->tag);
        OpenChaoJi_os_soft_timer_start(&context->running_data.a->tco_bsup, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCOBSUP);

        // 进入S4
        LOG_NOTICE("[%d]Charge S3 To S4", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S4_EV_SUSPEND;
    }

    // 充电机暂停充电状态判断
    if (OpenChaoJi_secc_app_get_charger_enable(context) == OPENCHAOJI_GBT27930_A_PAUSE_STATUS_CHARGE) // 充电机从暂停状态中恢复充电
    {
        LOG_DEBUG("[%d]Charge S3 secc recover from suspend", context->tag);

        // CCS报文数据变更为SPN3929=0x01 (状态数据, 实时刷新, 此处无需处理)
        // context->running_data.a->msg_ccs.state.bits.charging_permissible = OPENCHAOJI_GBT27930_A_PAUSE_STATUS_CHARGE;

        // 判断预充是否完成
        if (context->running_data.a->precharge_status == OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_FINISHED) // 预充完成
        {
            LOG_NOTICE("[%d]Charge S3 precharge finished", context->tag);

            // 恢复充电, 进入S2
            LOG_NOTICE("[%d]Charge S3 To S2", context->tag);
            return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S2_ENERGY_TRANS;
        }
    }

    // 继续等待, 保持S3
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S3_SE_SUSPEND;
}

static void OpenChaoJi_gbt27930_a_secc_prev_charge_s4_evcc_suspend(struct OpenChaoJi_secc_context * context) {}
static void OpenChaoJi_gbt27930_a_secc_post_charge_s4_evcc_suspend(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_charge_s4_evcc_suspend(struct OpenChaoJi_secc_context * context)
{
    LOG_DEBUG("[%d]Charge S4 evcc suspend", context->tag);

    // TCPccs定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tcp_ccs))
    {
        // 更新CCS报文内容
        context->running_data.a->msg_ccs.output_voltage_value = OpenChaoJi_secc_hal_power_module_get_voltage(context->hal_handle);
        context->running_data.a->msg_ccs.output_current_value = 4000 - OpenChaoJi_secc_hal_power_module_get_current(context->hal_handle);
        context->running_data.a->msg_ccs.cumulative_charging_time = OpenChaoJi_secc_app_get_charging_time(context);
        context->running_data.a->msg_ccs.state.bits.charging_permissible = OpenChaoJi_secc_app_get_charger_enable(context);

        // 发送CCS报文
        LOG_INFO("[%d]Charge S4 send ccs", context->tag);
        OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CCS, (uint8_t *)(&context->running_data.a->msg_ccs), sizeof(context->running_data.a->msg_ccs));

        // 重置TCPccs
        LOG_INFO("[%d]Charge S4 reset timer TCPccs", context->tag);
        OpenChaoJi_os_soft_timer_reset(&context->running_data.a->tcp_ccs);
    }

    // 接收车辆BCL报文
    if (context->running_data.a->msg_bcl_ok)
    {
        context->running_data.a->msg_bcl_ok = 0;
        LOG_INFO("[%d]Charge S4 bcl received", context->tag);

        // 重置TCObcl
        LOG_INFO("[%d]Charge S4 reset timer TCObcl", context->tag);
        OpenChaoJi_os_soft_timer_reset(&context->running_data.a->tco_bcl);
    }

    // TCObcl定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_bcl))
    {
        LOG_ERR("[%d]Charge S4 bcl timeout", context->tag);

        // 发送CEM报文, 此处只更新错误代码, 进入错误处理阶段后执行发送
        context->running_data.a->msg_cem.tout_code.bits.timeout_bcl = 0x01; // BCL超时

        // 进入S7
        LOG_ERR("[%d]Charge S4 To S7", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S7_ERROR;
    }

    // 接收车辆BCS报文
    if (context->running_data.a->msg_bcs_ok)
    {
        context->running_data.a->msg_bcs_ok = 0;

        // 重置TCObcs
        LOG_INFO("[%d]Charge S4 reset timer TCObcs", context->tag);
        OpenChaoJi_os_soft_timer_reset(&context->running_data.a->tco_bcs);
    }

    // TCObcs定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_bcs))
    {
        LOG_ERR("[%d]Charge S4 bcs timeout", context->tag);

        // 发送CEM报文, 此处只更新错误代码, 进入错误处理阶段后执行发送
        context->running_data.a->msg_cem.tout_code.bits.timeout_bcs = 0x01; // BCS超时

        // 进入S7
        LOG_ERR("[%d]Charge S4 To S7", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S7_ERROR;
    }

    // 接收车辆BSM报文
    if (context->running_data.a->msg_bsm_ok)
    {
        context->running_data.a->msg_bsm_ok = 0;

        LOG_INFO("[%d]Charge S4 bsm received", context->tag);

        // 首次接收到BSM报文时, 打开TCObsm
        if (!context->running_data.a->charge.bsm_rcvd_flag)
        {
            context->running_data.a->charge.bsm_rcvd_flag = 1;

            // 打开TCObsm
            LOG_INFO("[%d]Charge S4 start timer TCObsm", context->tag);
            OpenChaoJi_os_soft_timer_start(&context->running_data.a->tco_bsm, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCOBSM);
        }
        else
        {
            // 重置TCObsm
            LOG_INFO("[%d]Charge S4 reset timer TCObsm", context->tag);
            OpenChaoJi_os_soft_timer_reset(&context->running_data.a->tco_bsm);
        }
    }

    // TCObsm定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_bsm))
    {
        LOG_ERR("[%d]Charge S4 bsm timeout", context->tag);

        // 发送CEM报文, 此处只更新错误代码, 进入错误处理阶段后执行发送
        context->running_data.a->msg_cem.tout_code.bits.timeout_bsm = 0x01; // BSM超时

        // 进入S7
        LOG_ERR("[%d]Charge S4 To S7", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S7_ERROR;
    }

    // TCObsup定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_bsup))
    {
        LOG_ERR("[%d]Charge S4 EVCC Suspend Timeout", context->tag);

        // 更新停机代码
        context->running_data.a->msg_cst.stop_code.bits.fault_suspends = 0x01; // 充电机中止充电原因: 故障中止
        context->running_data.a->msg_cst.fault_code.bits.other_fault = 0x01;    // 充电机中止充电故障原因: 其他故障-车辆暂停充电超时

        // 进入S5
        LOG_ERR("[%d]Charge S4 To S5", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S5_EV_STOP;
    }

    // 车辆暂停充电状态判断 (BSM报文)
    if (context->running_data.a->msg_bsm.batt_state.bits.charge_enable == OPENCHAOJI_GBT27930_A_PAUSE_STATUS_CHARGE) // 车辆恢复充电
    {
        LOG_DEBUG("[%d]Charge S4 evcc recover from suspend", context->tag);

        // 充电机暂停充电状态判断
        if (OpenChaoJi_secc_app_get_charger_enable(context) == OPENCHAOJI_GBT27930_A_PAUSE_STATUS_CHARGE) // 充电机允许充电
        {
            // 判断预充是否完成
            if (context->running_data.a->precharge_status == OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_FINISHED) // 预充完成
            {
                LOG_NOTICE("[%d]Charge S4 precharge finished", context->tag);

                // 关闭TCObsup
                LOG_INFO("[%d]Charge S4 stop timer TCObsup", context->tag);
                OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bsup);

                // 恢复充电, 进入S2
                LOG_NOTICE("[%d]Charge S4 To S2", context->tag);
                return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S2_ENERGY_TRANS;
            }
        }
        else // 充电机暂停充电
        {
            // 关闭TCObsup
            LOG_INFO("[%d]Charge S4 stop timer TCObsup", context->tag);
            OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bsup);

            LOG_NOTICE("[%d]Charge S4 SECC Start Suspend", context->tag);

            // 充电机暂停充电, 进入S3
            LOG_NOTICE("[%d]Charge S4 To S3", context->tag);
            return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S3_SE_SUSPEND;
        }
    }

    // 继续等待, 保持S4
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S4_EV_SUSPEND;
}

static void OpenChaoJi_gbt27930_a_secc_prev_charge_s5_wait_bst(struct OpenChaoJi_secc_context * context)
{
    context->running_data.a->msg_bst_ok = 0;
    // 设置模块关机
    LOG_INFO("[%d]Charge S5 shutdown module", context->tag);
    OpenChaoJi_secc_hal_power_module_request_stop(context->hal_handle);
}
static void OpenChaoJi_gbt27930_a_secc_post_charge_s5_wait_bst(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_charge_s5_wait_bst(struct OpenChaoJi_secc_context * context)
{
    // SECC主动中止, 首次发送CST
    if (!context->running_data.a->charge.cst_send_flag)
    {
        context->running_data.a->charge.cst_send_flag = 1;

        LOG_INFO("[%d]Charge S5 stop all invalid timer", context->tag);

        // 关闭TCPcro
        LOG_INFO("[%d]Charge S5 stop timer TCPcro", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_cro);

        // 关闭TCPccs
        LOG_INFO("[%d]Charge S5 stop timer TCPccs", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_ccs);

        // 关闭TCObcl
        LOG_INFO("[%d]Charge S5 stop timer TCObcl", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bcl);

        // 关闭TCObsm
        LOG_INFO("[%d]Charge S5 stop timer TCObsm", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bsm);

        // 关闭TCObsup
        LOG_INFO("[%d]Charge S5 stop timer TCObsup", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bsup);

        // 发送CST报文
        LOG_INFO("[%d]Charge S5 send cst", context->tag);
        OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CST, (uint8_t *)(&context->running_data.a->msg_cst), sizeof(context->running_data.a->msg_cst));

        // 打开TCPcst
        LOG_INFO("[%d]Charge S5 start timer TCPcst", context->tag);
        OpenChaoJi_os_soft_timer_start(&context->running_data.a->tcp_cst, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCPCST);

        // 打开TCObst
        LOG_INFO("[%d]Charge S5 start timer TCObst", context->tag);
        OpenChaoJi_os_soft_timer_start(&context->running_data.a->tco_bst, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCOBST);

        // 打开TCObsd
        LOG_INFO("[%d]Charge S5 start timer TCObsd", context->tag);
        OpenChaoJi_os_soft_timer_start(&context->running_data.a->tco_bsd, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCOBSD);
    }

    // TCPcst定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tcp_cst))
    {
        // 发送CST报文
        LOG_INFO("[%d]Charge S5 send cst", context->tag);
        OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CST, (uint8_t *)(&context->running_data.a->msg_cst), sizeof(context->running_data.a->msg_cst));

        // 重置TCPcst
        LOG_INFO("[%d]Charge S5 reset timer TCPcst", context->tag);
        OpenChaoJi_os_soft_timer_reset(&context->running_data.a->tcp_cst);
    }

    // 接收车辆BST报文
    if (context->running_data.a->msg_bst_ok)
    {
        context->running_data.a->msg_bst_ok = 0;

        LOG_NOTICE("[%d]Charge S5 bst received", context->tag);

        // 关闭TCObst
        LOG_INFO("[%d]Charge S5 stop timer TCObst", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bst);

        // 进入S6
        LOG_NOTICE("[%d]Charge S5 To S6", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S6_STOPPED;
    }

    // TCObst定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_bst))
    {
        LOG_ERR("[%d]Charge S5 bst timeout", context->tag);

        // 关闭TCPcst
        LOG_INFO("[%d]Charge S5 stop timer TCPcst", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_cst);

        // 关闭TCObsd
        LOG_INFO("[%d]Charge S5 stop timer TCObsd", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bsd);

        // 发送CEM报文, 此处只更新错误代码, 进入错误处理阶段后执行发送
        context->running_data.a->msg_cem.tout_code.bits.timeout_bst = 0x01; // BST超时

        // 进入S7
        LOG_ERR("[%d]Charge S5 To S7", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S7_ERROR;
    }

    // 未收到, 未超时, 继续等待, 保持S5
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S5_EV_STOP;
}

static void OpenChaoJi_gbt27930_a_secc_prev_charge_s6_stopped(struct OpenChaoJi_secc_context * context) {}
static void OpenChaoJi_gbt27930_a_secc_post_charge_s6_stopped(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_charge_s6_stopped(struct OpenChaoJi_secc_context * context)
{
    // 充电机主动中止, 无需处理

    // 车辆主动中止, SECC接收到BST后直接跳转到该阶段（停机事件）, 此时需要SECC主动发送CST
    if (!context->running_data.a->charge.cst_send_flag)
    {
        LOG_INFO("[%d]Charge S6 stop all invalid timer", context->tag);

        // 关闭TCPcro
        LOG_INFO("[%d]Charge S6 stop timer TCPcro", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_cro);

        // 关闭TCPccs
        LOG_INFO("[%d]Charge S6 stop timer TCPccs", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_ccs);

        // 关闭TCObcl
        LOG_INFO("[%d]Charge S6 stop timer TCObcl", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bcl);

        // 关闭TCObsm
        LOG_INFO("[%d]Charge S6 stop timer TCObsm", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bsm);

        // 关闭TCObsup
        LOG_INFO("[%d]Charge S6 stop timer TCObsup", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bsup);

        // 关闭TCObst
        LOG_INFO("[%d]Charge S6 stop timer TCObst", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bst);

        // 发送CST报文 (充电阶段收到BST, 会直接跳转到S6进行停机交互)
        LOG_INFO("[%d]Charge S6 send cst", context->tag);
        OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CST, (uint8_t *)(&context->running_data.a->msg_cst), sizeof(context->running_data.a->msg_cst));

        // 打开TCPcst
        LOG_INFO("[%d]Charge S6 start timer TCPcst", context->tag);
        OpenChaoJi_os_soft_timer_start(&context->running_data.a->tcp_cst, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCPCST);

        // 打开TCObsd
        LOG_INFO("[%d]Charge S6 start timer TCObsd", context->tag);
        OpenChaoJi_os_soft_timer_start(&context->running_data.a->tco_bsd, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCOBSD);
    }

    // 进入充电结束阶段
    LOG_NOTICE("[%d]Charge S6 To End S0", context->tag);
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_END_S0_INIT;
}

static void OpenChaoJi_gbt27930_a_secc_prev_charge_s7_error(struct OpenChaoJi_secc_context * context) {}
static void OpenChaoJi_gbt27930_a_secc_post_charge_s7_error(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_charge_s7_error(struct OpenChaoJi_secc_context * context)
{
    LOG_INFO("[%d]Charge S7 stop all invalid timer", context->tag);

    // 关闭TCPcro
    LOG_INFO("[%d]Charge S7 stop timer TCPcro", context->tag);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_cro);

    // 关闭TCPccs
    LOG_INFO("[%d]Charge S7 stop timer TCPccs", context->tag);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_ccs);

    // 关闭TCObcl
    LOG_INFO("[%d]Charge S7 stop timer TCPbcl", context->tag);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bcl);

    // 关闭TCObsm
    LOG_INFO("[%d]Charge S7 stop timer TCObsm", context->tag);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bsm);

    // 关闭TCObsup
    LOG_INFO("[%d]Charge S7 stop timer TCObsup", context->tag);
    OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bsup);

    // 进入超时处理阶段
    LOG_ERR("[%d]Charge S7 To Error S0", context->tag);
    context->running_data.a->stop_ticks = OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_STOP_TIMEOUT;
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_ERROR_S0_INIT;
}

const struct OpenChaoJi_secc_module_status c_sytem_a_secc_status_array_charge[OPENCHAOJI_GBT27930_A_SECC_STATUS_CHARGE_NUM] = {
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S0_INIT,
        .name = "Charge.S0.Init",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_charge_s0_init,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_charge_s0_init,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_charge_s0_init,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S1_WAIT_BCL,
        .name = "Charge.S1.Wait_BCL",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_charge_s1_wait_bcl,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_charge_s1_wait_bcl,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_charge_s1_wait_bcl,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S2_ENERGY_TRANS,
        .name = "Charge.S2.Energy_Trans",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_charge_s2_energy_trans,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_charge_s2_energy_trans,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_charge_s2_energy_trans,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S3_SE_SUSPEND,
        .name = "Charge.S3.SECC_Suspend",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_charge_s3_secc_suspend,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_charge_s3_secc_suspend,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_charge_s3_secc_suspend,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S4_EV_SUSPEND,
        .name = "Charge.S4.EVCC_Suspend",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_charge_s4_evcc_suspend,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_charge_s4_evcc_suspend,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_charge_s4_evcc_suspend,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S5_EV_STOP,
        .name = "Charge.S5.Wait_BST",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_charge_s5_wait_bst,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_charge_s5_wait_bst,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_charge_s5_wait_bst,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S6_STOPPED,
        .name = "Charge.S6.Stopped",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_charge_s6_stopped,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_charge_s6_stopped,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_charge_s6_stopped,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S7_ERROR,
        .name = "Charge.S7.Error",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_charge_s7_error,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_charge_s7_error,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_charge_s7_error,
    },
};

const struct OpenChaoJi_secc_module c_gbt27930_a_secc_module_charge =
{
    .module_id = OPENCHAOJI_GBT27930_A_MODULE_CHARGE,
    .name = "Charge",
    .status_array = c_sytem_a_secc_status_array_charge,
    .status_array_len = OPENCHAOJI_GBT27930_A_SECC_STATUS_CHARGE_NUM,
};


/* --------------  END 模块 银河龙芯 -------------- */

static void OpenChaoJi_gbt27930_a_secc_prev_end_s0_init(struct OpenChaoJi_secc_context * context)
{
    LOG_NOTICE("[%d]End Status Start", context->tag);
    LOG_NOTICE("[%d]End S0 init", context->tag);
}
static void OpenChaoJi_gbt27930_a_secc_post_end_s0_init(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_end_s0_init(struct OpenChaoJi_secc_context * context)
{
    // 进入S1
    LOG_NOTICE("[%d]End S0 T0 S1", context->tag);
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_END_S1_EV_STATISTICS;
}

static void OpenChaoJi_gbt27930_a_secc_prev_end_s1_wait_bsd(struct OpenChaoJi_secc_context * context)
{
    context->running_data.a->msg_bsd_ok = 0;
}
static void OpenChaoJi_gbt27930_a_secc_post_end_s1_wait_bsd(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_end_s1_wait_bsd(struct OpenChaoJi_secc_context * context)
{
    // TCPcst定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tcp_cst))
    {
        // 发送CST报文
        LOG_INFO("[%d]End S1 send cst", context->tag);
        OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CST, (uint8_t *)(&context->running_data.a->msg_cst), sizeof(context->running_data.a->msg_cst));

        // 重置TCPcst
        LOG_INFO("[%d]End S1 reset timer TCPcst", context->tag);
        OpenChaoJi_os_soft_timer_reset(&context->running_data.a->tcp_cst);
    }

    // 接收车辆BSD报文
    if (context->running_data.a->msg_bsd_ok)
    {
        LOG_NOTICE("[%d]End S1 bsd received", context->tag);

        // 关闭TCPcst
        LOG_INFO("[%d]End S1 reset timer TCPcst", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_cst);

        // 关闭TCObsd
        LOG_INFO("[%d]End S1 stop timer TCObsd", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_bsd);

        context->running_data.a->msg_csd.charger_id = OpenChaoJi_secc_app_get_charger_id(context); // 充电机编号
        context->running_data.a->msg_csd.cumulative_charging_time = OpenChaoJi_secc_app_get_charging_time(context);
        context->running_data.a->msg_csd.output_energy = OpenChaoJi_secc_app_get_output_energy(context);

        // 发送CSD报文
        LOG_INFO("[%d]End S1 send csd", context->tag);
        OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CSD, (uint8_t *)(&context->running_data.a->msg_csd), sizeof(context->running_data.a->msg_csd));

        // 打开TCPcsd
        LOG_INFO("[%d]End S1 start timer TCPcsd", context->tag);
        OpenChaoJi_os_soft_timer_start(&context->running_data.a->tcp_csd, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCPCSD);

        // 打开TCOcsd - 充电结束阶段, SECC退出充电前持续发送CSD报文的时间, 不少于5次(当前默认5秒≈20次)
        LOG_INFO("[%d]End S1 start timer TCOcsd", context->tag);
        OpenChaoJi_os_soft_timer_start(&context->running_data.a->tco_csd, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCOCSD);

        // 进入S2
        LOG_NOTICE("[%d]End S1 To S2", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_END_S2_SE_STATISTICS;
    }

    // TCObsd定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_bsd))
    {
        LOG_ERR("[%d]End S1 bsd timeout", context->tag);

        // 关闭TCPcst
        LOG_INFO("[%d]End S1 stop timer TCPcst", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_cst);

        // 发送CEM报文, 此处只更新错误代码, 进入错误处理阶段后执行发送
        context->running_data.a->msg_cem.tout_code.bits.timeout_bsd = 0x01; // BSD超时

        // 进入S4
        LOG_ERR("[%d]End S1 To S4", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_END_S4_ERROR;
    }

    // 未收到, 未超时, 继续等待, 保持S1
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_END_S1_EV_STATISTICS;
}

static void OpenChaoJi_gbt27930_a_secc_prev_end_s2_send_csd(struct OpenChaoJi_secc_context * context) {}
static void OpenChaoJi_gbt27930_a_secc_post_end_s2_send_csd(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_end_s2_send_csd(struct OpenChaoJi_secc_context * context)
{
    // TCPcsd定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tcp_csd))
    {
        // 发送CSD报文
        LOG_INFO("[%d]End S2 send csd", context->tag);
        OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CSD, (uint8_t *)(&context->running_data.a->msg_csd), sizeof(context->running_data.a->msg_csd));

        // 重置TCPcsd
        LOG_INFO("[%d]End S2 reset timer TCPcsd", context->tag);
        OpenChaoJi_os_soft_timer_reset(&context->running_data.a->tcp_csd);
    }

    // TCOcsd定时器到 (CSD发送不少于5次, 最短时间: 5秒≈20次, 最长时间: 停机泄放超时时间)
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_csd) && \
        (context->running_data.a->stop_status >= OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_FINISHED))
    {
        LOG_NOTICE("[%d]End S2 csd finished", context->tag);

        // 关闭TCPcsd
        LOG_INFO("[%d]End S2 stop timer TCPcsd", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_csd);

        // 断开C1 C2（如未断）
        LOG_NOTICE("[%d]End S2 cut off C1 C2 (confirm)", context->tag);
        OpenChaoJi_secc_hal_gbt_close_dc_relay(context->hal_handle, 0);

        // 断开泄放（如未断）
        LOG_NOTICE("[%d]End S2 stop vent (confirm)", context->tag);
        OpenChaoJi_secc_hal_vent_request_stop(context->hal_handle);

        // 断开S3 S4, 停止交互
        LOG_NOTICE("[%d]End S2 cut off S3 S4", context->tag);
        OpenChaoJi_secc_hal_gbt_a_close_aux_power(context->hal_handle, 0);

        // 进入S3
        LOG_NOTICE("[%d]End S2 To S3", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_END_S3_FINISHED;
    }

    // 未超时, 继续等待, 保持S2
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_END_S2_SE_STATISTICS;
}

static void OpenChaoJi_gbt27930_a_secc_prev_end_s3_finished(struct OpenChaoJi_secc_context * context) {}
static void OpenChaoJi_gbt27930_a_secc_post_end_s3_finished(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_end_s3_finished(struct OpenChaoJi_secc_context * context)
{
    // 电子锁解锁
    LOG_NOTICE("[%d]End S3 release elock", context->tag);
    OpenChaoJi_secc_hal_gbt_a_lock(context->hal_handle, 0);

    // 复位充电启动标识
    context->app_permit_charge = 0;

    LOG_NOTICE("[%d]End Status Finished", context->tag);

    // 退出充电
    LOG_NOTICE("[%d]End S3 Return to Idle", context->tag);
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_IDLE_S0_IDLE;
}

static void OpenChaoJi_gbt27930_a_secc_prev_end_s4_error(struct OpenChaoJi_secc_context * context) {}
static void OpenChaoJi_gbt27930_a_secc_post_end_s4_error(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_end_s4_error(struct OpenChaoJi_secc_context * context)
{
    // 进入错误处理阶段
    LOG_ERR("[%d]End S4 To Error S0", context->tag);
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_ERROR_S0_INIT;
}

const struct OpenChaoJi_secc_module_status c_sytem_a_secc_status_array_end[OPENCHAOJI_GBT27930_A_SECC_STATUS_END_NUM] = {
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_END_S0_INIT,
        .name = "End.S0.Init",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_end_s0_init,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_end_s0_init,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_end_s0_init,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_END_S1_EV_STATISTICS,
        .name = "End.S1.Wait_BSD",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_end_s1_wait_bsd,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_end_s1_wait_bsd,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_end_s1_wait_bsd,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_END_S2_SE_STATISTICS,
        .name = "End.S2.Send_CSD",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_end_s2_send_csd,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_end_s2_send_csd,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_end_s2_send_csd,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_END_S3_FINISHED,
        .name = "End.S3.Finished",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_end_s3_finished,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_end_s3_finished,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_end_s3_finished,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_END_S4_ERROR,
        .name = "End.S4.Error",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_end_s4_error,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_end_s4_error,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_end_s4_error,
    },
};

const struct OpenChaoJi_secc_module c_gbt27930_a_secc_module_end =
{
    .module_id = OPENCHAOJI_GBT27930_A_MODULE_END,
    .name = "End",
    .status_array = c_sytem_a_secc_status_array_end,
    .status_array_len = OPENCHAOJI_GBT27930_A_SECC_STATUS_END_NUM,
};

/* 错误处理 */

static void OpenChaoJi_gbt27930_a_secc_prev_error_s0_init(struct OpenChaoJi_secc_context * context)
{
    LOG_NOTICE("[%d]Error Status Start", context->tag);
    LOG_NOTICE("[%d]Error S0 init", context->tag);

    // 设置模块关机 GB/T 18487.1 B.4.7.4
    OpenChaoJi_secc_hal_power_module_request_stop(context->hal_handle);
}
static void OpenChaoJi_gbt27930_a_secc_post_error_s0_init(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_error_s0_init(struct OpenChaoJi_secc_context * context)
{
    if (context->running_data.a->msg_cem.tout_code.all & (~0xF0C0F0FC)) // 充电机检测到通信超时错误
    {
        LOG_NOTICE("[%d]Error S0 cem mode", context->tag);

        // 发送CEM报文
        LOG_INFO("[%d]Error S0 send cem", context->tag);
        OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CEM, (uint8_t *)(&context->running_data.a->msg_cem), sizeof(context->running_data.a->msg_cem));

        // 打开TCPcem
        LOG_INFO("[%d]Error S0 start timer TCPcem", context->tag);
        OpenChaoJi_os_soft_timer_start(&context->running_data.a->tcp_cem, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCPCEM);

        // 打开TCOcep (错误处理超时定时器)
        LOG_INFO("[%d]Error S0 start timer TCOcep", context->tag);
        OpenChaoJi_os_soft_timer_start(&context->running_data.a->tco_cep, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCOCEP);

        // 进入S1
        LOG_NOTICE("[%d]Error S0 To S1", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_ERROR_S1_CEM;
    }
    else // 接收到车辆BEM报文(车辆检测到超时)
    {
        LOG_NOTICE("[%d]Error S0 bem mode", context->tag);

        // 打开TCOcep
        LOG_INFO("[%d]Error S0 start timer TCOcep", context->tag);
        OpenChaoJi_os_soft_timer_start(&context->running_data.a->tco_cep, OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCOCEP);

        // 进入S2
        LOG_NOTICE("[%d]Error S0 To S2", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_ERROR_S2_BEM;
    }
}

static void OpenChaoJi_gbt27930_a_secc_prev_error_s1_cem(struct OpenChaoJi_secc_context * context) {}
static void OpenChaoJi_gbt27930_a_secc_post_error_s1_cem(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_error_s1_cem(struct OpenChaoJi_secc_context * context)
{
    // TCPcem定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tcp_cem))
    {
        // 发送CEM报文
        LOG_INFO("[%d]Error S1 send cem", context->tag);
        OpenChaoJi_gbt27930_a_secc_send_normal(context, OPENCHAOJI_GBT27930_A_PID_TAG_CEM, (uint8_t *)(&context->running_data.a->msg_cem), sizeof(context->running_data.a->msg_cem));

        // 重置TCPcem
        LOG_INFO("[%d]Error S1 reset timer TCPcem", context->tag);
        OpenChaoJi_os_soft_timer_reset(&context->running_data.a->tcp_cem);
    }

    // 错误处理完成状态判断
    if (context->running_data.a->stop_status == OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_FINISHED)
    {
        LOG_NOTICE("[%d]Error S1 handling result is ok", context->tag);

        // 关闭TCPcem
        LOG_INFO("[%d]Error S1 stop timer TCPcem", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_cem);

        // 关闭TCOcep
        LOG_INFO("[%d]Error S1 stop timer TCOcep", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_cep);

        // 进入S3
        LOG_NOTICE("[%d]Error S1 To S3", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_ERROR_S3_CHECK;
    }

    // TCOcep定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_cep))
    {
        LOG_ERR("[%d]Error S1 handling timeout", context->tag);

        // 关闭TCPcem
        LOG_INFO("[%d]Error S1 stop timer TCPcem", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tcp_cem);

        // 断开C1 C2（如未断）
        LOG_NOTICE("[%d]Error S1 cut off C1 C2 (confirm)", context->tag);
        OpenChaoJi_secc_hal_gbt_close_dc_relay(context->hal_handle, 0);

        // 断开泄放（如未断）
        LOG_NOTICE("[%d]Error S1 stop vent (confirm)", context->tag);
        OpenChaoJi_secc_hal_vent_request_stop(context->hal_handle);

        // 断开S3 S4, 停止交互
        LOG_NOTICE("[%d]Error S1 cut off S3 S4", context->tag);
        OpenChaoJi_secc_hal_gbt_a_close_aux_power(context->hal_handle, 0);

        // 进入S5
        LOG_ERR("[%d]Error S1 To S5", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_ERROR_S5_FINISHED;
    }

    // 未超时, 继续等待, 保持S1
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_ERROR_S1_CEM;
}

static void OpenChaoJi_gbt27930_a_secc_prev_error_s2_bem(struct OpenChaoJi_secc_context * context) {}
static void OpenChaoJi_gbt27930_a_secc_post_error_s2_bem(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_error_s2_bem(struct OpenChaoJi_secc_context * context)
{
    // 错误处理完成状态判断
    if (context->running_data.a->stop_status == OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_FINISHED)
    {
        LOG_NOTICE("[%d]Error S2 handling result is ok", context->tag);

        // 关闭TCOcep
        LOG_INFO("[%d]Error S2 stop timer TCOcep", context->tag);
        OpenChaoJi_os_soft_timer_stop(&context->running_data.a->tco_cep);

        // 进入S3
        LOG_NOTICE("[%d]Error S2 To S3", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_ERROR_S3_CHECK;
    }

    // TCOcep定时器到
    if (OpenChaoJi_os_soft_timer_is_timeout(&context->running_data.a->tco_cep))
    {
        LOG_ERR("[%d]Error S2 handling timeout", context->tag);

        // 断开C1 C2（如未断）
        LOG_NOTICE("[%d]Error S2 cut off C1 C2 (confirm)", context->tag);
        OpenChaoJi_secc_hal_gbt_close_dc_relay(context->hal_handle, 0);

        // 断开泄放（如未断）
        LOG_NOTICE("[%d]Error S2 stop vent (confirm)", context->tag);
        OpenChaoJi_secc_hal_vent_request_stop(context->hal_handle);

        // 断开S3 S4, 停止交互
        LOG_NOTICE("[%d]Error S2 cut off S3 S4", context->tag);
        OpenChaoJi_secc_hal_gbt_a_close_aux_power(context->hal_handle, 0);

        // 进入S5
        LOG_ERR("[%d]Error S2 To S5", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_ERROR_S5_FINISHED;
    }

    // 未超时, 继续等待
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_ERROR_S2_BEM;
}

static void OpenChaoJi_gbt27930_a_secc_prev_error_s3_check(struct OpenChaoJi_secc_context * context) {}
static void OpenChaoJi_gbt27930_a_secc_post_error_s3_check(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_error_s3_check(struct OpenChaoJi_secc_context * context)
{
    LOG_INFO("[%d]Error S3 check for reconnect", context->tag);

    // 重连条件 BCP BRO BCL BCS + CML CRO CCS
    if ((context->running_data.a->reconnect_cnt < OpenChaoJi_secc_app_get_permit_reconnect_cnt(context)) && \
        (context->running_data.a->msg_cem.tout_code.bits.timeout_bcp == 1 || \
        context->running_data.a->msg_cem.tout_code.bits.timeout_bro == 1 || \
        context->running_data.a->msg_cem.tout_code.bits.timeout_bcl == 1 || \
        context->running_data.a->msg_cem.tout_code.bits.timeout_bcs == 1 || \
        context->running_data.a->msg_bem.tout_code.bits.cml == 1 || \
        context->running_data.a->msg_bem.tout_code.bits.cro == 1 || \
        context->running_data.a->msg_bem.tout_code.bits.ccs == 1 ))
    {
        // 置位通信重连标识, 通信重连次数增加
        context->running_data.a->reconnect_flag = 1;
        context->running_data.a->reconnect_cnt += 1;

        LOG_NOTICE("[%d]Error S3 ready to reconnect, cnt is %d", context->tag, context->running_data.a->reconnect_cnt);

        // 进入S4
        LOG_NOTICE("[%d]Error S3 To S4", context->tag);
        return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_ERROR_S4_RETRY;
    }

    LOG_NOTICE("[%d]Error S3 reconnect cancel", context->tag);

    // 断开S3 S4, 停止交互
    LOG_INFO("[%d]Error S3 cut off S3 S4", context->tag);
    OpenChaoJi_secc_hal_gbt_a_close_aux_power(context->hal_handle, 0);

    // 进入S5
    LOG_NOTICE("[%d]Error S3 To S5", context->tag);
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_ERROR_S5_FINISHED;
}

static void OpenChaoJi_gbt27930_a_secc_prev_error_s4_retry(struct OpenChaoJi_secc_context * context) {}
static void OpenChaoJi_gbt27930_a_secc_post_error_s4_retry(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_error_s4_retry(struct OpenChaoJi_secc_context * context)
{
    LOG_NOTICE("[%d]Reconnect Start", context->tag);
    OpenChaoJi_gbt27930_a_secc_running_data_timer_reset(context);

    // 进入充电握手阶段
    LOG_NOTICE("[%d]Error S4 To Handshake S0", context->tag);
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_HANDSHAKE_S0_INIT;
}

static void OpenChaoJi_gbt27930_a_secc_prev_error_s5_finished(struct OpenChaoJi_secc_context * context) {}
static void OpenChaoJi_gbt27930_a_secc_post_error_s5_finished(struct OpenChaoJi_secc_context * context) {}
static int  OpenChaoJi_gbt27930_a_secc_loop_error_s5_finished(struct OpenChaoJi_secc_context * context)
{
    // 电子锁解锁
    LOG_NOTICE("[%d]Error S5 release elock", context->tag);
    OpenChaoJi_secc_hal_gbt_a_lock(context->hal_handle, 0);

    // 复位充电启动标识
    context->app_permit_charge = 0;

    LOG_NOTICE("[%d]Error Status Exit", context->tag);

    // 退出充电
    LOG_NOTICE("[%d]Error S5 Return to Idle", context->tag);
    return OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_IDLE_S0_IDLE;
}

const struct OpenChaoJi_secc_module_status c_sytem_a_secc_status_array_error[OPENCHAOJI_GBT27930_A_SECC_STATUS_ERROR_NUM] = {
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_ERROR_S0_INIT,
        .name = "Error.S0.Init",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_error_s0_init,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_error_s0_init,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_error_s0_init,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_ERROR_S1_CEM,
        .name = "Error.S1.Send_CEM",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_error_s1_cem,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_error_s1_cem,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_error_s1_cem,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_ERROR_S2_BEM,
        .name = "Error.S2.Rcvd_BEM",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_error_s2_bem,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_error_s2_bem,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_error_s2_bem,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_ERROR_S3_CHECK,
        .name = "Error.S3.Reconnect_Check",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_error_s3_check,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_error_s3_check,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_error_s3_check,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_ERROR_S4_RETRY,
        .name = "Error.S4.Reconnect",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_error_s4_retry,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_error_s4_retry,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_error_s4_retry,
    },
    {
        .module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_ERROR_S5_FINISHED,
        .name = "Error.S5.Finished",

        .prev_func = OpenChaoJi_gbt27930_a_secc_prev_error_s5_finished,
        .post_func = OpenChaoJi_gbt27930_a_secc_post_error_s5_finished,
        .loop_func = OpenChaoJi_gbt27930_a_secc_loop_error_s5_finished,
    },
};

const struct OpenChaoJi_secc_module c_gbt27930_a_secc_module_error =
{
    .module_id = OPENCHAOJI_GBT27930_A_MODULE_ERROR,
    .name = "Error",
    .status_array = c_sytem_a_secc_status_array_error,
    .status_array_len = OPENCHAOJI_GBT27930_A_SECC_STATUS_ERROR_NUM,
};

/**
 * 通用子模块处理, 即跨越一般功能模块的一些全局功能的处理. 例如链路检测, 连接检测等
 * 由于连接检测需要快速响应, 厂家底层实现时可以考虑通过中断等方式触发后立即调用service方法来触发处理流程, 而不必等到定时处理
*/

static int OpenChaoJi_gbt27930_a_secc_sub_module_func(struct OpenChaoJi_secc_context * context)
{
    // TODO: 各种错误处理, 参考18487和27930

    if (context->current_module_status_id > OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_IDLE_S0_IDLE && \
        context->current_module_status_id < OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S5_EV_STOP)
    {
        if (OpenChaoJi_secc_utility_session_is_connected(context->context_session) == OPENCHAOJI_SECC_UTILITY_SESSION_CONNECT_STATUS_DISCONNECTED)
        {
            // 没有session_start暂时不判断
            // LOG_ERR("[%d]Lost Connection", context->tag);
            // return OpenChaoJi_gbt27930_a_secc_stop_failed(context, OPENCHAOJI_GBT27930_A_END_CODE_SECC_FAULT, OPENCHAOJI_GBT27930_A_END_REASON_SECC_FAULT_OTHER);
        }

        struct OpenChaoJi_secc_hal_samp samp_value;
        OpenChaoJi_secc_hal_sampling_value(context->hal_handle, &samp_value);

        // GB/T 27930 11.3.9 充电机急停故障
        if (OpenChaoJi_secc_hal_is_emergency_pushed(context->hal_handle))
        {
            LOG_ERR("[%d]Emergency Pushed", context->tag);
            context->running_data.a->stop_ticks = OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_STOP_FAULT;
            return OpenChaoJi_gbt27930_a_secc_stop_emergency(context, OPENCHAOJI_GBT27930_A_END_CODE_SECC_FAULT, OPENCHAOJI_GBT27930_A_END_REASON_SECC_FAULT_EMERGENCY);
        }

        // GB/T 18487.1 B.4.6 人工中止、达到充电机设定的条件中止
        if (!context->app_permit_charge)
        {
            // APP中止包含正常停机和故障停机，如人工中止、APP检测到充电机异常时下发中止
            // TODO: 需要知道APP中止原因明细
            LOG_ERR("[%d]App Stop", context->tag);

            // 正常中止
            context->running_data.a->stop_ticks = OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_STOP_NORMAL(samp_value.current);
            // 故障中止
            // context->running_data.a->stop_ticks = OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_STOP_FAULT;

            return OpenChaoJi_gbt27930_a_secc_stop_normal(context, OPENCHAOJI_GBT27930_A_END_CODE_SECC_NORMAL, OPENCHAOJI_GBT27930_A_END_REASON_SECC_NORMAL_USER);
        }

        // GB/T 18487.1 B.4.6 收到车辆中止充电报文(BST)
        if (context->running_data.a->msg_bst_ok)
        {
            LOG_ERR("[%d]EVCC Stop", context->tag);

            if (context->running_data.a->msg_bst.fault_code.all)
                context->running_data.a->stop_ticks = OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_STOP_FAULT;
            else if (context->running_data.a->msg_bst.error_code.all)
                context->running_data.a->stop_ticks = OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_STOP_FAULT;
            else
                context->running_data.a->stop_ticks = OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_STOP_NORMAL(samp_value.current);

            return OpenChaoJi_gbt27930_a_secc_stop_normal(context, OPENCHAOJI_GBT27930_A_END_CODE_SECC_NORMAL, OPENCHAOJI_GBT27930_A_END_REASON_SECC_NORMAL_BST);
        }

        // GB/T 27930 5.4 电流超过-400A
        if (context->running_data.a->msg_bcp.allow_current > 4000   || \
            context->running_data.a->msg_bcl.target_current > 4000  || \
            context->running_data.a->msg_bcs.measured_current > 4000 )
        {
            LOG_ERR("[%d]EVCC Stop", context->tag);
            context->running_data.a->stop_ticks = OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_STOP_ERROR;
            return OpenChaoJi_gbt27930_a_secc_stop_failed(context, OPENCHAOJI_GBT27930_A_END_CODE_SECC_FAULT, OPENCHAOJI_GBT27930_A_END_REASON_SECC_FAULT_OTHER);
        }

        // GB/T 27930 11.3.9 CST中止充电故障/错误原因明细
        if (context->current_module_status_id > OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_TRIGGER_S0_CONNECT_CONFIRM)
        {
            // GB/T 18487.1 B.4.7.5 检测点1电压异常, 车辆连接不可靠
            if (!OpenChaoJi_secc_utility_pilot_is_evcc_connected(context->context_pilot))
            {
                LOG_ERR("[%d]CC1 Error", context->tag);
                context->running_data.a->stop_ticks = OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_STOP_FAULT;
                return OpenChaoJi_gbt27930_a_secc_stop_failed(context, OPENCHAOJI_GBT27930_A_END_CODE_SECC_FAULT, OPENCHAOJI_GBT27930_A_END_REASON_SECC_FAULT_CC1);
            }
        }

        if (context->current_module_status_id > OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_TRIGGER_S1_LOCK_CONFIRM)
        {
            // GB/T 18487.1 B.4.7.9 电子锁未可靠锁止
            if (!OpenChaoJi_secc_hal_gbt_a_is_locked(context->hal_handle))
            {
                LOG_ERR("[%d]Electronic Lock is fault", context->tag);
                context->running_data.a->stop_ticks = OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_STOP_ERROR;
                return OpenChaoJi_gbt27930_a_secc_stop_failed(context, OPENCHAOJI_GBT27930_A_END_CODE_SECC_FAULT, OPENCHAOJI_GBT27930_A_END_REASON_SECC_FAULT_LOCK);
            }
        }

        if (context->current_module_status_id > OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S0_INIT)
        {
            // GB/T 18487.1 B.4.7.6 车辆接口处充电电压超过车辆最高允许充电总电压+15V
            if (samp_value.voltage_out > (context->running_data.a->msg_bcp.allow_voltage + 150))
            {
                LOG_ERR("[%d]EVCC Volatge Error: Vout=%d, Vbcp_allow=%d", context->tag, samp_value.voltage_out, context->running_data.a->msg_bcp.allow_voltage);
                context->running_data.a->stop_ticks = OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_STOP_ERROR;
                return OpenChaoJi_gbt27930_a_secc_stop_failed(context, OPENCHAOJI_GBT27930_A_END_CODE_SECC_FAULT, OPENCHAOJI_GBT27930_A_END_REASON_SECC_FAULT_OTHER);
            }

            // GB/T 27930 11.3.4 BSM电池状态异常
            if (context->running_data.a->msg_bsm.batt_state.all & 0x0FFF)
            {
                LOG_ERR("[%d]EVCC State Error: Bsm_State=0x%04x", context->tag, context->running_data.a->msg_bsm.batt_state.all);
                context->running_data.a->stop_ticks = OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_STOP_FAULT;
                return OpenChaoJi_gbt27930_a_secc_stop_failed(context, OPENCHAOJI_GBT27930_A_END_CODE_SECC_FAULT, OPENCHAOJI_GBT27930_A_END_REASON_SECC_FAULT_BSM);
            }

            // TODO: 故障代码、故障条件判断
            // GB/T 18487.1 B.4.7.1 充电机出现不能继续充电的故障
            // GB/T 18487.1 B.4.7.10 负载突降
        }

        if (context->current_module_status_id == OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CONFIG_S6_PRE_CHARGE)
        {
            // 执行预充 GB/T 18487.1-2023 B.4.5
            LOG_DEBUG("[%d]Config: precharge", context->tag);
            OpenChaoJi_gbt27930_a_secc_pre_charge(context, context->running_data.a->msg_bcp.measured_voltage);

            // 预充故障
            if (context->running_data.a->precharge_status == OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_ERROR)
            {
                LOG_ERR("[%d]Config: precharge failed", context->tag);
                context->running_data.a->stop_ticks = OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_STOP_FAULT;
                return OpenChaoJi_gbt27930_a_secc_stop_failed(context, OPENCHAOJI_GBT27930_A_END_CODE_SECC_FAULT, OPENCHAOJI_GBT27930_A_END_REASON_SECC_FAULT_PRECHARGE);
            }
        }

        if (context->current_module_status_id == OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S3_SE_SUSPEND || \
            context->current_module_status_id == OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S4_EV_SUSPEND)
        {
            // GB/T 18487.1 B.4.5 暂停充电过程中C5、C6断开, 中止充电
            if (samp_value.voltage_out < 600)
            {
                LOG_ERR("[%d]EVCC Volatge Error: Vout=%d", context->tag, samp_value.voltage_out);
                context->running_data.a->stop_ticks = OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_STOP_ERROR;
                return OpenChaoJi_gbt27930_a_secc_stop_failed(context, OPENCHAOJI_GBT27930_A_END_CODE_SECC_FAULT, OPENCHAOJI_GBT27930_A_END_REASON_SECC_FAULT_OTHER);
            }

            // 充电暂停/恢复条件判断
            if ((OpenChaoJi_secc_app_get_charger_enable(context) == OPENCHAOJI_GBT27930_A_PAUSE_STATUS_CHARGE) && \
                (context->running_data.a->msg_bsm.batt_state.bits.charge_enable == OPENCHAOJI_GBT27930_A_PAUSE_STATUS_CHARGE))
            {
                // 停机状态复位
                context->running_data.a->stop_status = OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_INIT;
                context->running_data.a->stop_ticks = OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_STOP_NORMAL(0);

                // 执行预充 GB/T 18487.1-2023 B.4.5
                LOG_DEBUG("[%d]Suspend: precharge", context->tag);
                OpenChaoJi_gbt27930_a_secc_pre_charge(context, context->running_data.a->msg_bcs.measured_voltage);

                // 预充故障
                if (context->running_data.a->precharge_status == OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_ERROR)
                {
                    LOG_ERR("[%d]Suspend: precharge failed", context->tag);
                    context->running_data.a->stop_ticks = OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_STOP_FAULT;
                    return OpenChaoJi_gbt27930_a_secc_stop_failed(context, OPENCHAOJI_GBT27930_A_END_CODE_SECC_FAULT, OPENCHAOJI_GBT27930_A_END_REASON_SECC_FAULT_PRECHARGE);
                }
            }
            else // 充电机或车辆暂停充电
            {
                // 预充状态复位
                context->running_data.a->precharge_status = OPENCHAOJI_GBT27930_A_SECC_PRECHARGE_STATUS_INIT;

                // 停机泄放 GB/T 18487.1-2023 B.4.5
                LOG_DEBUG("[%d]Suspend: stopping", context->tag);
                OpenChaoJi_gbt27930_a_secc_stopping(context);

                if (context->running_data.a->stop_status == OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_ERROR)
                {
                    LOG_ERR("[%d]Suspend: stop failed", context->tag);
                    context->running_data.a->stop_ticks = OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_STOP_FAULT;
                    return OpenChaoJi_gbt27930_a_secc_stop_failed(context, OPENCHAOJI_GBT27930_A_END_CODE_SECC_FAULT, OPENCHAOJI_GBT27930_A_END_REASON_SECC_FAULT_OTHER);
                }
            }
        }

        if (context->current_module_status_id > OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_HANDSHAKE_S0_INIT)
        {
            // GB/T 27930 附录A.2
            if (context->running_data.a->msg_bem_ok)
            {
                LOG_ERR("[%d]EVCC Communicate Error", context->tag);
                context->running_data.a->stop_ticks = OPENCHAOJI_GBT27930_A_PID_TIMEOUT_SECC_TCO_STOP_TIMEOUT;
                return OpenChaoJi_gbt27930_a_secc_rcvd_bem(context);
            }
        }
    }

    if (context->current_module_status_id >= OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_CHARGE_S5_EV_STOP && \
        context->current_module_status_id <= OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_ERROR_S2_BEM)
    {
        // GB/T 18487.1-2023 B.4.6-B.4.7 停机泄放
        if (context->running_data.a->stop_status < OPENCHAOJI_GBT27930_A_SECC_STOPPING_STATUS_FINISHED)
        {
            LOG_DEBUG("[%d]stopping", context->tag);
            OpenChaoJi_gbt27930_a_secc_stopping(context);
        }
    }

    return context->current_module_status_id;
}

/**
 * 收发数据的通用处理方法
 * 收是在执行所有system操作前统一执行, 用于同步对端状态
 * 发是在执行所有system后统一执行, 用于把本方状态同步给对端
*/
void OpenChaoJi_gbt27930_a_secc_data_read_func(struct OpenChaoJi_secc_context * context)
{
    // 先把对端数据都收过来
    OpenChaoJi_secc_utility_session_service_try_recv(context->context_session);

    // 读空缓冲区, 解析到system数据处理区
    struct OpenChaoJi_utility_data_buff_recv_data recv_data;
    while (OpenChaoJi_secc_utility_session_data_read(context->context_session, &recv_data) == 0)
    {
        OpenChaoJi_gbt27930_a_secc_parse_data(context, &recv_data);
        if (!recv_data.recv_data.src_free)
        {
            OpenChaoJi_os_free(recv_data.recv_data.data);
        }
    }
}
void OpenChaoJi_gbt27930_a_secc_data_write_func(struct OpenChaoJi_secc_context * context)
{
    OpenChaoJi_secc_utility_session_service_try_send(context->context_session);
}

/**
 * 启停充电/获取充电等方法, 供App调用
*/
int OpenChaoJi_gbt27930_a_secc_app_start_func(struct OpenChaoJi_secc_context * context, struct OpenChaoJi_secc_app_start_parameter * app_start_parameter)
{
    LOG_ALERT("[%d]secc_app_start_func", context->tag);

    context->running_data.a->app_start_parameter = *app_start_parameter;
    context->app_permit_charge = 1;

    LOG_NOTICE("[%d]secc_app_param: max_vol=%d, min_vol=%d, max_cur=%d, min_cur=%d", context->tag \
                                                                                   , context->running_data.a->app_start_parameter.parameter_max_charging_volt \
                                                                                   , context->running_data.a->app_start_parameter.parameter_min_charging_volt \
                                                                                   , context->running_data.a->app_start_parameter.parameter_max_charging_curr \
                                                                                   , context->running_data.a->app_start_parameter.parameter_min_charging_curr );

    return 0;
}
int OpenChaoJi_gbt27930_a_secc_app_stop_func(struct OpenChaoJi_secc_context * context)
{
    // TODO: 增加参数 enum stopReason, enum stopType

    LOG_ALERT("[%d]secc_app_stop_func", context->tag);

    context->app_permit_charge = 0;
    return 0;
}
int  OpenChaoJi_gbt27930_a_secc_app_get_status_func(struct OpenChaoJi_secc_context * context, struct OpenChaoJi_secc_context_status * status)
{
	status->current_module_status_id = context->current_module_status_id;
	status->demand_current = context->running_data.a->msg_bcl.target_current;
	status->demand_voltage = context->running_data.a->msg_bcl.target_voltage;
	status->soc = (uint16_t)context->running_data.a->msg_bcs.soc;
	status->remain_time = context->running_data.a->msg_bcs.expected_time;
	memcpy(status->evin, context->running_data.a->msg_brm.evin, 17);

    return 0;
}


int OpenChaoJi_secc_create_system_gbt27930_a(struct OpenChaoJi_secc_context * context)
{
    /* 注册secc系统, 生成secc系统模块状态表 */
    context->secc_gbt27930_system = OpenChaoJi_os_malloc(sizeof(struct OpenChaoJi_secc_gbt27930_system));
    if (context->secc_gbt27930_system == NULL)
    {
        goto FAILED_CREATE;
    }
    memset(context->secc_gbt27930_system, 0x00, sizeof(struct OpenChaoJi_secc_gbt27930_system));

    context->secc_gbt27930_system->module_array = OpenChaoJi_os_malloc(OPENCHAOJI_GBT27930_A_MODULE_NUM * sizeof(struct OpenChaoJi_secc_module *));
    if (context->secc_gbt27930_system->module_array == NULL)
    {
        goto FAILED_CREATE;
    }
	memset(context->secc_gbt27930_system->module_array, 0x00, OPENCHAOJI_GBT27930_A_MODULE_NUM * sizeof(struct OpenChaoJi_secc_module *));
	context->secc_gbt27930_system->module_array_len = OPENCHAOJI_GBT27930_A_MODULE_NUM;

    context->secc_gbt27930_system->module_array[OPENCHAOJI_GBT27930_A_MODULE_IDLE]          = &c_gbt27930_a_secc_module_idle;
    context->secc_gbt27930_system->module_array[OPENCHAOJI_GBT27930_A_MODULE_TRIGGER]       = &c_gbt27930_a_secc_module_trigger;
    context->secc_gbt27930_system->module_array[OPENCHAOJI_GBT27930_A_MODULE_HANDSHAKE]     = &c_gbt27930_a_secc_module_handshake;
    context->secc_gbt27930_system->module_array[OPENCHAOJI_GBT27930_A_MODULE_CONFIG]        = &c_gbt27930_a_secc_module_config;
    context->secc_gbt27930_system->module_array[OPENCHAOJI_GBT27930_A_MODULE_CHARGE]        = &c_gbt27930_a_secc_module_charge;
    context->secc_gbt27930_system->module_array[OPENCHAOJI_GBT27930_A_MODULE_END]           = &c_gbt27930_a_secc_module_end;
    context->secc_gbt27930_system->module_array[OPENCHAOJI_GBT27930_A_MODULE_ERROR]         = &c_gbt27930_a_secc_module_error;

    context->secc_gbt27930_system->sub_module_func      = OpenChaoJi_gbt27930_a_secc_sub_module_func;
    context->secc_gbt27930_system->data_read_func       = OpenChaoJi_gbt27930_a_secc_data_read_func;
    context->secc_gbt27930_system->data_write_func      = OpenChaoJi_gbt27930_a_secc_data_write_func;
    context->secc_gbt27930_system->app_start_func       = OpenChaoJi_gbt27930_a_secc_app_start_func;
    context->secc_gbt27930_system->app_stop_func        = OpenChaoJi_gbt27930_a_secc_app_stop_func;
    context->secc_gbt27930_system->app_get_status_func  = OpenChaoJi_gbt27930_a_secc_app_get_status_func;

    /* 创建运行时数据 */
    context->running_data.a = OpenChaoJi_os_malloc(sizeof(struct OpenChaoJi_secc_gbt27930_a_data));
    if (context->running_data.a == NULL)
    {
        goto FAILED_CREATE;
    }
    // memset(context->running_data.a, 0x00, sizeof(struct OpenChaoJi_secc_gbt27930_a_data));

    OpenChaoJi_gbt27930_a_secc_running_data_reset(context);

    context->current_module_status_id = OPENCHAOJI_GBT27930_A_SECC_STATUS_ID_IDLE_S0_IDLE;
    context->current_status_ticks = OpenChaoJi_os_get_ticks();

    return 0;

FAILED_CREATE:

    OpenChaoJi_secc_destory_system_gbt27930_a(context);

    return -1;
}


/**
 * @brief: 销毁系统上下文中system相关
 * @param {OpenChaoJi_secc_context *} context 系统上下文指针
 * @return {*}
 */
void OpenChaoJi_secc_destory_system_gbt27930_a(struct OpenChaoJi_secc_context * context)
{
    if (context == NULL)
    {
        return;
    }

    if (context->secc_gbt27930_system != NULL)
    {
        if (context->secc_gbt27930_system->module_array == NULL)
        {
            OpenChaoJi_os_free(context->secc_gbt27930_system->module_array);
        }

        OpenChaoJi_os_free(context->secc_gbt27930_system);
    }

    if (context->running_data.a != NULL)
    {
        OpenChaoJi_os_free(context->running_data.a);
    }
}

/**********************************以下为A类系统报文解析函数*******************************************/
/**
 * @brief  解析接收报文
 *
 * @param  context 系统上下文指针，包含必要的环境信息。
 * @param  recv_data 接收的数据结构
 * @return 成功返回0，失败返回-1。
 */
int OpenChaoJi_gbt27930_a_secc_parse_data(struct OpenChaoJi_secc_context * context, struct OpenChaoJi_utility_data_buff_recv_data * recv_data)
{
	if(recv_data->tag.gbt.msg_type != OPENCHAOJI_GBT27930_SYSTEM_A_MSG)
	{
        LOG_ERR("Not MsgType GBT-A");
        goto PARSE_FAILED;
    }

    struct OpenChaoJi_gbt27930_a_msg msg;
    if (!OpenChaoJi_gbt27930_a_msg_decode(&msg, recv_data->tag.gbt.pf, recv_data->recv_data.data, recv_data->recv_data.len, context->running_data.a->protocol_version))
    {
        goto PARSE_FAILED;
    }

    bool changed = false;
    switch(recv_data->tag.gbt.pf)
    {
    case OPENCHAOJI_GBT27930_A_PGN_BHM:
        changed = OpenChaoJi_gbt27930_a_msg_cmpcpy_bhm(context->tag
            , &context->running_data.a->msg_bhm
            , &msg.msg.bhm
        );
        if (!context->running_data.a->msg_bhm_ok)
        {
            LOG_WARNING("[%d]msg_bhm_ok", context->tag);
            context->running_data.a->msg_bhm_ok = 1;
            changed = true;
        }
        break;

    case OPENCHAOJI_GBT27930_A_PGN_BRM:
        changed = OpenChaoJi_gbt27930_a_msg_cmpcpy_brm(context->tag
            , &context->running_data.a->msg_brm
            , &msg.msg.brm
        );
        if (!context->running_data.a->msg_brm_ok)
        {
            LOG_WARNING("[%d]msg_brm_ok", context->tag);
            context->running_data.a->msg_brm_ok = 1;
            changed = true;
        }
        break;

    case OPENCHAOJI_GBT27930_A_PGN_BCP:
        changed = OpenChaoJi_gbt27930_a_msg_cmpcpy_bcp(context->tag
            , &context->running_data.a->msg_bcp
            , &msg.msg.bcp
        );
        if (!context->running_data.a->msg_bcp_ok)
        {
            LOG_WARNING("[%d]msg_bcp_ok", context->tag);
            context->running_data.a->msg_bcp_ok = 1;
            changed = true;
        }
        break;

    case OPENCHAOJI_GBT27930_A_PGN_BRO:
        changed = OpenChaoJi_gbt27930_a_msg_cmpcpy_bro(context->tag
            , &context->running_data.a->msg_bro
            , &msg.msg.bro
        );
        if (!context->running_data.a->msg_bro_ok)
        {
            LOG_WARNING("[%d]msg_bro_ok", context->tag);
            context->running_data.a->msg_bro_ok = 1;
            changed = true;
        }
        break;

    case OPENCHAOJI_GBT27930_A_PGN_BCL:
        changed = OpenChaoJi_gbt27930_a_msg_cmpcpy_bcl(context->tag
            , &context->running_data.a->msg_bcl
            , &msg.msg.bcl
        );
        if (!context->running_data.a->msg_bcl_ok)
        {
            LOG_INFO("[%d]msg_bcl_ok", context->tag);
            context->running_data.a->msg_bcl_ok = 1;
            // changed = true; // 周期数据, 变更时打印
        }
        break;

    case OPENCHAOJI_GBT27930_A_PGN_BCS:
        changed = OpenChaoJi_gbt27930_a_msg_cmpcpy_bcs(context->tag
            , &context->running_data.a->msg_bcs
            , &msg.msg.bcs
        );
        if (!context->running_data.a->msg_bcs_ok)
        {
            LOG_INFO("[%d]msg_bcs_ok", context->tag);
            context->running_data.a->msg_bcs_ok = 1;
            // changed = true; // 周期数据, 变更时打印
        }
        break;

    case OPENCHAOJI_GBT27930_A_PGN_BSM:
        changed = OpenChaoJi_gbt27930_a_msg_cmpcpy_bsm(context->tag
            , &context->running_data.a->msg_bsm
            , &msg.msg.bsm
        );
        if (!context->running_data.a->msg_bsm_ok)
        {
            LOG_INFO("[%d]msg_bsm_ok", context->tag);
            context->running_data.a->msg_bsm_ok = 1;
            // changed = true; // 周期数据, 变更时打印
        }
        break;

    case OPENCHAOJI_GBT27930_A_PGN_BMV:
        changed = OpenChaoJi_gbt27930_a_msg_cmpcpy_bmv(context->tag
            , &context->running_data.a->msg_bmv
            , &msg.msg.bmv
        );
        if (!context->running_data.a->msg_bmv_ok)
        {
            LOG_WARNING("[%d]msg_bmv_ok", context->tag);
            context->running_data.a->msg_bmv_ok = 1;
            changed = true;
        }
        break;

    case OPENCHAOJI_GBT27930_A_PGN_BMT:
        changed = OpenChaoJi_gbt27930_a_msg_cmpcpy_bmt(context->tag
            , &context->running_data.a->msg_bmt
            , &msg.msg.bmt
        );
        if (!context->running_data.a->msg_bmt_ok)
        {
            LOG_WARNING("[%d]msg_bmt_ok", context->tag);
            context->running_data.a->msg_bmt_ok = 1;
            changed = true;
        }
        break;

    case OPENCHAOJI_GBT27930_A_PGN_BSP:
        changed = OpenChaoJi_gbt27930_a_msg_cmpcpy_bsp(context->tag
            , &context->running_data.a->msg_bsp
            , &msg.msg.bsp
        );
        if (!context->running_data.a->msg_bsp_ok)
        {
            LOG_WARNING("[%d]msg_bsp_ok", context->tag);
            context->running_data.a->msg_bsp_ok = 1;
            changed = true;
        }
        break;

    case OPENCHAOJI_GBT27930_A_PGN_BST:
        changed = OpenChaoJi_gbt27930_a_msg_cmpcpy_bst(context->tag
            , &context->running_data.a->msg_bst
            , &msg.msg.bst
        );
        if (!context->running_data.a->msg_bst_ok)
        {
            LOG_WARNING("[%d]msg_bst_ok", context->tag);
            context->running_data.a->msg_bst_ok = 1;
            changed = true;
        }
        break;

    case OPENCHAOJI_GBT27930_A_PGN_BSD:
        changed = OpenChaoJi_gbt27930_a_msg_cmpcpy_bsd(context->tag
            , &context->running_data.a->msg_bsd
            , &msg.msg.bsd
        );
        if (!context->running_data.a->msg_bsd_ok)
        {
            LOG_WARNING("[%d]msg_bsd_ok", context->tag);
            context->running_data.a->msg_bsd_ok = 1;
            changed = true;
        }
        break;

    case OPENCHAOJI_GBT27930_A_PGN_BEM:
        changed = OpenChaoJi_gbt27930_a_msg_cmpcpy_bem(context->tag
            , &context->running_data.a->msg_bem
            , &msg.msg.bem
        );
        if (!context->running_data.a->msg_bem_ok)
        {
            LOG_WARNING("[%d]msg_bem_ok", context->tag);
            context->running_data.a->msg_bem_ok = 1;
            changed = true;
        }
        break;

    default:
        LOG_ERR("[%d]Unknown PID[%02X]", context->tag, recv_data->tag.gbt.pf);
        goto PARSE_FAILED;
    }

    // 接收数据发生变化必须打出完整报文, 打印级别是INFO则把所有报文打印出来
    if ((changed) || ((OpenChaoJi_debug_get_log_level() & DBGL_INFO) != 0))
    {
        // 周期性报文, 即使INFO级别也不打印, 只变化才打印
        if (!changed && !s_gbt_a_public_debug_enable)
        {
            return 0;
        }

        OpenChaoJi_gbt27930_a_msg_log(&msg);
        if ((OpenChaoJi_debug_get_log_level() & DBGL_INFO) != 0)
        {
            LOG_DATA_CHANGE("<-[%02X][%d]", msg.pid, recv_data->recv_data.len);
            LOG_DATA_BUFF_CHANGE(recv_data->recv_data.data, recv_data->recv_data.len);
        }
    }

	return 0;

PARSE_FAILED:
    LOG_ERR("[%d]Invalid MsgFromEvcc", context->tag);
    LOG_BUFF_ERR(recv_data->recv_data.data, recv_data->recv_data.len);
    return -1;
}

#endif
